diff --git a/.github/workflows/verify-chains-manifest.yml b/.github/workflows/chains-manifest-consistency.yml similarity index 100% rename from .github/workflows/verify-chains-manifest.yml rename to .github/workflows/chains-manifest-consistency.yml diff --git a/.github/workflows/deployed-code-verification.yml b/.github/workflows/deployed-code-verification.yml new file mode 100644 index 0000000..ed6abe2 --- /dev/null +++ b/.github/workflows/deployed-code-verification.yml @@ -0,0 +1,61 @@ +name: Deployed Code Verification + +on: + pull_request: + paths: + - 'addresses/**' + - 'verify/**' + workflow_dispatch: + +jobs: + deployed-code-verification: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/checkout@v4 + with: + repository: euler-xyz/euler-verifier + # Engine pinned by commit SHA; bump deliberately via PR. + ref: 534dcf9eda294a46c208c7b8767fdd76dfc2fd29 + path: .verifier + + - uses: pnpm/action-setup@v4 + with: + package_json_file: .verifier/package.json + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + cache-dependency-path: .verifier/pnpm-lock.yaml + - uses: foundry-rs/foundry-toolchain@v1 + + - run: pnpm install --frozen-lockfile + working-directory: .verifier + + - name: Validate manifests (schema, SHA-only pins, audits integrity) + run: pnpm tsx src/validate-manifests.ts --manifest $GITHUB_WORKSPACE/verify/manifest.json --audits $GITHUB_WORKSPACE/verify/audits.json + working-directory: .verifier + + - name: Completeness (every deployed address has a manifest entry) + run: pnpm tsx src/check-completeness.ts --manifest $GITHUB_WORKSPACE/verify/manifest.json --addresses $GITHUB_WORKSPACE/addresses + working-directory: .verifier + + - name: Determine changed entries + id: changed + run: | + git fetch --no-tags --depth=1 origin $GITHUB_BASE_REF + CHAINS=$(git diff --name-only origin/$GITHUB_BASE_REF...HEAD -- addresses verify/manifest.json | grep -oE 'addresses/[0-9]+' | grep -oE '[0-9]+' | sort -u | paste -sd, -) + echo "chains=$CHAINS" >> $GITHUB_OUTPUT + echo "changed chains: ${CHAINS:-none}" + + - name: Bytecode-verify changed chains + if: steps.changed.outputs.chains != '' + env: + CHAINS: ${{ steps.changed.outputs.chains }} + run: | + set -e + for c in ${CHAINS//,/ }; do + pnpm verify --manifest $GITHUB_WORKSPACE/verify/manifest.json --addresses $GITHUB_WORKSPACE/addresses --chain "$c" --no-explorer + done + working-directory: .verifier diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml deleted file mode 100644 index dc07cf0..0000000 --- a/.github/workflows/verify.yml +++ /dev/null @@ -1,110 +0,0 @@ -name: Contract Verification - -on: - push: - branches: [master] - paths: - - 'addresses/**' - workflow_dispatch: - inputs: - network: - description: 'Network name or chain ID to verify (leave empty to verify changed chains)' - required: false - type: string - -jobs: - verify: - runs-on: ubuntu-latest - timeout-minutes: 60 - - steps: - - name: Checkout euler-interfaces - uses: actions/checkout@v4 - with: - fetch-depth: 2 - - - name: Detect changed chains - id: detect - run: | - if [ "${{ github.event_name }}" = "push" ]; then - CHAINS=$(git diff --name-only HEAD~1 HEAD -- addresses/ | grep -oP 'addresses/\K[0-9]+' | sort -u | tr '\n' ' ') - elif [ -n "${{ inputs.network }}" ]; then - CHAINS="${{ inputs.network }}" - else - # Manual trigger with no input: discover all chains - CHAINS="discover" - fi - echo "chains=$CHAINS" >> "$GITHUB_OUTPUT" - echo "Chains to verify: $CHAINS" - - - name: Clone euler-verifier - run: git clone --depth 1 https://github.com/euler-xyz/euler-verifier.git /tmp/euler-verifier - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Install uv - run: pip install uv - - - name: Install dependencies - working-directory: /tmp/euler-verifier - run: uv sync --no-install-project - - - name: Symlink euler-interfaces into verifier - run: | - rm -rf /tmp/euler-verifier/euler-interfaces - ln -s "$GITHUB_WORKSPACE" /tmp/euler-verifier/euler-interfaces - - - name: Setup source repositories - run: | - mkdir -p /tmp/euler-verifier/repos - - echo "Cloning evk-periphery..." - git clone --depth 50 https://github.com/euler-xyz/evk-periphery /tmp/euler-verifier/repos/evk-periphery - cd /tmp/euler-verifier/repos/evk-periphery - git fetch --tags - git submodule update --init --recursive - cd /tmp/euler-verifier - - echo "Cloning euler-earn..." - git clone --depth 50 https://github.com/euler-xyz/euler-earn /tmp/euler-verifier/repos/euler-earn-standalone - cd /tmp/euler-verifier/repos/euler-earn-standalone - git fetch --tags --all - cd /tmp/euler-verifier - - echo "Cloning euler-swap..." - git clone --depth 50 https://github.com/euler-xyz/euler-swap /tmp/euler-verifier/repos/euler-swap-standalone - cd /tmp/euler-verifier/repos/euler-swap-standalone - git fetch --tags --all - git fetch --depth=1 origin tag eulerswap-1.0 - cd /tmp/euler-verifier - - echo "Done setting up repositories" - - - name: Run verification - env: - ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }} - run: | - cd /tmp/euler-verifier - CHAINS="${{ steps.detect.outputs.chains }}" - - if [ "$CHAINS" = "discover" ]; then - uv run python verify.py --discover || true - else - for CHAIN_ID in $CHAINS; do - echo "==========================================" - echo "Verifying chain: $CHAIN_ID" - echo "==========================================" - uv run python verify.py "$CHAIN_ID" || true - done - fi - - - name: Upload verification reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: verification-reports - path: /tmp/euler-verifier/results/ - retention-days: 30 diff --git a/README.md b/README.md new file mode 100644 index 0000000..a2cdf1c --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +# euler-interfaces + +Canonical addresses, ABIs, and interface definitions for the deployed Euler +protocol contracts across all supported chains. + +## ✅ Deployed Code Verification + +Every security-relevant Euler contract is **verified at the bytecode level**: +the on-chain runtime code is proven equal to a build of an exact, recorded +source commit — block explorers are never in the trust path — and each +deployment is diffed against its component's most recent **audited baseline**, +so any code beyond audited revisions is visible as a real diff. + +**[Browse the per-chain verification reports →](verify/README.md)** + +- [`verify/manifest.json`](verify/manifest.json) — source provenance for every + contract (repo + commit SHA + build profile), bytecode-proven +- [`verify/audits.json`](verify/audits.json) — the audit registry backing the + baselines +- [`verify/baselines.json`](verify/baselines.json) — one audited baseline per + component, with derivations +- Reports are named by chain ID (e.g. [`verify/1.md`](verify/1.md) for + Ethereum mainnet) and are regenerated by CI whenever addresses or + verification inputs change; verification is a required gate on such PRs. + +Anyone can reproduce the proofs with [euler-verifier](https://github.com/euler-xyz/euler-verifier) +using only public RPC endpoints — no API keys or secrets required. + +## Layout + +| Path | Contents | +|------|----------| +| `addresses//` | Deployed contract addresses per chain | +| `abis/` | Contract ABIs | +| `interfaces/` | Solidity interface definitions | +| `verify/` | Bytecode verification reports and provenance manifests | +| `EulerChains.json`, `chains.js` | Supported chain metadata | + +## Security + +See [SECURITY.md](SECURITY.md) for the disclosure policy, and the +[verification reports](verify/README.md) for what is deployed where. diff --git a/verify/1.md b/verify/1.md new file mode 100644 index 0000000..71f681a --- /dev/null +++ b/verify/1.md @@ -0,0 +1,842 @@ +# Ethereum Mainnet — Deployed Code Verification + +Chain ID: 1 · Bytecode-proven: **20/21** · Canonical: 1 + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0x0D52d06c…`](https://etherscan.io/address/0x0D52d06ceB8Dcdeeb40Cfd9f17489B350dD7F8a3) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `48762e01` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0xd9Fcd98c…`](https://etherscan.io/address/0xd9Fcd98c322942075A5C3860693e9f4f03AAE07b) | [`euler-governance`](https://github.com/euler-xyz/euler-governance) | 🏛 canonical | long-established (see note) | canonical 2021 token | +| eulOFTAdapter | [`0x3Bf1bD5D…`](https://etherscan.io/address/0x3Bf1bD5DB4457d22A85d45791B6291b98D0fC5b5) | [`evk-periphery@ccd2debc`](https://github.com/euler-xyz/evk-periphery/tree/ccd2debce48ed857c7766bb1955591cfac996d91) | ✅ `e74a0c71` | ≡ baseline | — | +| eVaultFactory | [`0x29a56a1b…`](https://etherscan.io/address/0x29a56a1b8214D9Cf7c5561811750D5cBDb45CC8e) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0x8Ff1C814…`](https://etherscan.io/address/0x8Ff1C814719096b61aBf00Bb46EAd0c9A529Dd7D) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `8c001272` | +1/−1 vs baseline | one fee-share default parameter | +| evc | [`0x0C9a3dd6…`](https://etherscan.io/address/0x0C9a3dd6b8F28529d72d7f9cE918D493519EE383) | [`ethereum-vault-connector@084b3228`](https://github.com/euler-xyz/ethereum-vault-connector/tree/084b32284ba643921f8d21bff3ddaf0c4e08d754) | ✅ `5b470906` | ≡ baseline | — | +| oracleRouterFactory | [`0x70B3f6F6…`](https://etherscan.io/address/0x70B3f6F61b7Bf237DF04589DdAA842121072326A) | [`evk-periphery@05b0acb8`](https://github.com/euler-xyz/evk-periphery/tree/05b0acb8bfb64e663293ab8b236c72c6b3df86ae) | ✅ `fd6ae566` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0x4cD6BF1D…`](https://etherscan.io/address/0x4cD6BF1D183264c02Be7748Cb5cd3A47d013351b) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0xf3e62139…`](https://etherscan.io/address/0xf3e621395fc714B90dA337AA9108771597b4E696) | [`evk-periphery@7a233058`](https://github.com/euler-xyz/evk-periphery/tree/7a23305815ccb4198c117c2d6fcfe8421fe336e3) | ✅ `8d4a5058` | ≡ baseline | — | +| sequenceRegistry | [`0xEADDD216…`](https://etherscan.io/address/0xEADDD21618ad5Deb412D3fD23580FD461c106B54) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0xB1C777BE…`](https://etherscan.io/address/0xB1C777BE7965dCdE810645497CC1e6e5997BD6C5) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `2fc2cdd1` | +3/−5 vs baseline | formatting only | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0x59709B02…`](https://etherscan.io/address/0x59709B029B140C853FE28d277f83C3a65e308aF4) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `c9ee150e` | +18/−18 vs baseline | import-path style only | +| eulerEarnPublicAllocator | [`0x8fdCb80a…`](https://etherscan.io/address/0x8fdCb80a2894F0dC052c8d52D22544DC90274800) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV1Factory | [`0xb013be1D…`](https://etherscan.io/address/0xb013be1D0D380C13B58e889f412895970A2Cf228) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `7c9a247e` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Implementation | [`0xc35a0FDA…`](https://etherscan.io/address/0xc35a0FDA69e9D71e68C0d9CBb541Adfd21D6B117) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `20cae9a4` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Periphery | [`0x208fF5Eb…`](https://etherscan.io/address/0x208fF5Eb543814789321DaA1B5Eb551881D16b06) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `703cfc72` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV2Factory | [`0xD0521333…`](https://etherscan.io/address/0xD05213331221fAB8a3C387F2affBb605Bb04DF5F) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `4bdd5d47` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0x8B0E044E…`](https://etherscan.io/address/0x8B0E044E364F2cE913799d53b300e15A6974DC97) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `408124d9` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0xD3a349EE…`](https://etherscan.io/address/0xD3a349EE0A21eA0A7E9513ac236ae614b5FD513E) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `f98bd760` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0x5171Aed0…`](https://etherscan.io/address/0x5171Aed04Fa9551DB484F07c853F252Bc6F53b63) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `83e2e2c4` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0x5FcCB843…`](https://etherscan.io/address/0x5FcCB84363F020c0cADE052C9c654aABF932814A) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `42c58b74` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0x7Dd834c7844710435Bd471B7499b16421ee84f3C` | ✅ | ✅ | +| Token | `0x8a58aecbE677682D0F037C67F37F5a7a2E94973c` | ✅ | ✅ | +| Vault | `0xB4Ad4D9C02c01b01Cf586C16f01C58c73c7f0188` | ✅ | ✅ | +| Borrowing | `0x639156f8fEB0cD88205e4861A0224Ec169605acF` | ✅ | ✅ | +| Liquidation | `0x16fa62D8c322a6156fb5eF267342A3C7952AD23C` | ✅ | ✅ | +| RiskManager | `0x402c858DAc359dc1165b782c22d2524F672Ca376` | ✅ | ✅ | +| BalanceForwarder | `0xA252aF9208E53c0AC6a79A5d0933A8D1F184FEE5` | ✅ | ✅ | +| Governance | `0xa61f5016F2cd5cec12d091f871fcE1e1df5f0b67` | ✅ | ✅ | + +## EulerSwap V2 management implementation (unpacked from the implementation) + +EulerSwap delegatecalls management functions into a separate contract whose address is the public immutable `managementImpl`; it is verified from the same euler-swap pin. + +| Contract | Address | Bytecode | Embedded-immutable cross-check | +|----------|---------|----------|-------------------------------| +| EulerSwapManagement | `0xA6C1dDC10fB13fdd998a4940a883aA952F5ef86a` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnFactory, eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) (eulerSwapV1Factory, eulerSwapV1Implementation, eulerSwapV1Periphery): + +Tag eulerswap-1.0 (official V1 release), descendant of the baseline. src delta: SPDX headers UNLICENSED→GPL (14 files) + PR #99 event hoisting (new Events.sol; hook emits Swap with sender). No state-machine or math changes. foundry optimizer_runs raised 10000→1000000 post-audit, pre-deployment. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..ce71a2c 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..39fe65b 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..1befa2e 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {Owned} from "solmate/src/auth/Owned.sol"; +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`ccd2debc`](https://github.com/euler-xyz/evk-periphery/tree/ccd2debce48ed857c7766bb1955591cfac996d91) (eulOFTAdapter): + +Adapter files blob-identical to the baseline; as the mainnet proxy implementation it carries the Paladin #02 fix (_disableInitializers). The Oct-2025 OFT fee-collector workstream around this commit touched only OFTFeeCollector/OFTGulper, not the adapters. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`084b3228`](https://github.com/euler-xyz/ethereum-vault-connector/tree/084b32284ba643921f8d21bff3ddaf0c4e08d754) (evc): + +Equals the baseline — the mainnet EVC deployment IS the audited fixes-included commit. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, eVaultImplementation, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`05b0acb8`](https://github.com/euler-xyz/evk-periphery/tree/05b0acb8bfb64e663293ab8b236c72c6b3df86ae) (oracleRouterFactory): + +Factory blobs identical across all four deployed pins. Delta vs baseline: the src/OracleFactory→src/EulerRouterFactory rename (content-neutral) and +10/−1 in EulerRouterFactory.sol — commit 59243614 threading the EVC address through the factory constructor into the embedded EulerRouter. That pass-through mirrors the router's EVC integration, which WAS audited on the oracle side (Cantina finding 443 fix + onlyEVCAccountOwner enhancement, approved by yaudit-oracle-2024-comp-fixes); the factory shell itself was not re-reviewed after this change. + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`09457185`](https://github.com/euler-xyz/euler-price-oracle/tree/0945718510a696b3a98eeb18b42065cfbdb91c1b)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`7a233058`](https://github.com/euler-xyz/evk-periphery/tree/7a23305815ccb4198c117c2d6fcfe8421fe336e3) (rEUL): + +Mainnet deployment (commit on the evk-periphery deployment-mainnet-reul branch): source byte-identical to the public 2024-10-30 post-fixes state f61809fd — component files identical to the audited baseline — narrowed to the RewardToken compile unit with a no-longer-resolvable submodule reference removed. Compiled at the repo profile (0.8.24, runs 20000, cancun). + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (swapVerifier): + +Descendant of the baseline by 3 days (the merge adding the Enigma report PDF). src/Swaps delta is 100% non-semantic forge-fmt re-wrapping. This IS the Enigma-fixes-included state as deployed on 13 chains. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +index b70618d3..d210ab47 100644 +--- a/src/Swaps/MigrationHelper.sol ++++ b/src/Swaps/MigrationHelper.sol +@@ -95,10 +95,7 @@ contract MigrationHelper is EVCUtil { + /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. + /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying + /// the user's permit can only ever drain their own balance. +- function transferBalanceFromSender(address token, uint256 maxAmount, address to) +- external +- returns (uint256 amount) +- { ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) external returns (uint256 amount) { + amount = IERC20(token).balanceOf(_msgSender()); + if (amount > maxAmount) amount = maxAmount; + // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index 23a3c2fd..ec881e76 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -69,7 +69,8 @@ contract SwapVerifier is MigrationHelper { + /// @param receiver The address to transfer the asset to + /// @param amountMin The minimum amount of the asset that must be available before transfer + /// @param deadline A timestamp after which the transfer will revert +- /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if the minimum is met ++ /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if ++ /// the minimum is met + function verifyAmountMinAndTransfer(address asset, address receiver, uint256 amountMin, uint256 deadline) external { + if (deadline < block.timestamp) revert SwapVerifier_pastDeadline(); +``` + +## Canonical contracts + +- **EUL** (`0xd9Fcd98c322942075A5C3860693e9f4f03AAE07b`): Canonical EUL governance token: contract Eul (contracts/governance/Eul.sol) in euler-xyz/euler-governance — an OpenZeppelin-based ERC20 with Votes/Permit and AccessControl, plus a treasury mint restricted to at most 2.718% of supply per year. Deployed at the end of 2021 (last source change 2021-12-30, commit 1249ea8b) and in continuous use since; documented here as provenance context rather than re-proven from a commit pin. BailSec performed a retrospective re-audit of exactly the deployed revision in June 2025 (bailsec-eul-erc20-2025: 4 informational findings, all acknowledged — the deployed contract is immutable). This token is the lock/unlock asset held by the mainnet OFT adapter; the bridged EUL on all other chains is the separate ERC20BurnableMintable, bytecode-proven in those chains’ reports. + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/130.md b/verify/130.md new file mode 100644 index 0000000..25e8e87 --- /dev/null +++ b/verify/130.md @@ -0,0 +1,1070 @@ +# Unichain — Deployed Code Verification + +Chain ID: 130 · Bytecode-proven: **21/21** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0xFbD12fbC…`](https://unichain.blockscout.com/address/0xFbD12fbC91311A8f17598b935e35205EAF16Aa75) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `47294620` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0xE9C43e09…`](https://unichain.blockscout.com/address/0xE9C43e09C5FA733bCC2aEAa96063A4a60147AA09) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `0b021e3f` | ≡ baseline | — | +| eulOFTAdapter | [`0x41a11d85…`](https://unichain.blockscout.com/address/0x41a11d85577Bb21743E11Eca62e2b241DC1eD5C0) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `1036d1c0` | ≡ baseline | — | +| eVaultFactory | [`0xbAd8b5BD…`](https://unichain.blockscout.com/address/0xbAd8b5BDFB2bcbcd78Cc9f1573D3Aad6E865e752) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0x71d72507…`](https://unichain.blockscout.com/address/0x71d7250732591C41D1BdeB1EA0Ee730E138E0c8b) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `8c001272` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0x2A117696…`](https://unichain.blockscout.com/address/0x2A1176964F5D7caE5406B627Bf6166664FE83c60) | [`ethereum-vault-connector@a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) | ✅ `b12f6d72` | +58/−11 vs baseline | EVCUtil helper + signer-exclusion hardening | +| oracleRouterFactory | [`0xE551288F…`](https://unichain.blockscout.com/address/0xE551288F0D82C10bBF517DBA66E15C60BF87FE8f) | [`evk-periphery@96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0xdCD02E4e…`](https://unichain.blockscout.com/address/0xdCD02E4eA8cd273498D315AD8c047305f8480656) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0x1b0e3Da5…`](https://unichain.blockscout.com/address/0x1b0e3Da51b2517E09aE74CD31b708e46B9158E8b) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0x08799a00…`](https://unichain.blockscout.com/address/0x08799a00BC4a74890d65f77828cd2BFbBFcD96dB) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0x49eB1C5B…`](https://unichain.blockscout.com/address/0x49eB1C5B56AA221965C3130d472ac9318f01f934) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `2fc2cdd1` | +3/−5 vs baseline | formatting only | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0xD785adD5…`](https://unichain.blockscout.com/address/0xD785adD5F081F56616898E45b90dE307e3DC7d3E) | [`euler-earn@773453b1`](https://github.com/euler-xyz/euler-earn/tree/773453b1f4a6f1d27a1cd0c6d8f6ada572503b23) | ✅ `c9ee150e` | ≡ baseline | — | +| eulerEarnPublicAllocator | [`0x68a823a4…`](https://unichain.blockscout.com/address/0x68a823a484a9D5A8daBB55c4d4d8006a45E557A9) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV1Factory | [`0x45b146BC…`](https://unichain.blockscout.com/address/0x45b146BC07c9985589B52df651310e75C6BE066A) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `7c9a247e` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Implementation | [`0xd91B0bfA…`](https://unichain.blockscout.com/address/0xd91B0bfACA4691E6Aca7E0E83D9B7F8917989a03) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `20cae9a4` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Periphery | [`0xdAAF468d…`](https://unichain.blockscout.com/address/0xdAAF468d84DD8945521Ea40297ce6c5EEfc7003a) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `703cfc72` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV2Factory | [`0xf211d70E…`](https://unichain.blockscout.com/address/0xf211d70Ed785f0e981E9F3188804Af43734502F1) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `4bdd5d47` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0x144f1715…`](https://unichain.blockscout.com/address/0x144f1715c673dA83917B09A5B4C23E2d72c8D411) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `408124d9` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0xAD335516…`](https://unichain.blockscout.com/address/0xAD335516c6E17815d9DD543fBCDFE325F8563E13) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `f98bd760` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0xeA96Ed68…`](https://unichain.blockscout.com/address/0xeA96Ed6896aB1F00e4Fc28C75D8e6655e56Cef85) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `83e2e2c4` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0x9D9ce154…`](https://unichain.blockscout.com/address/0x9D9ce1540b986eF77c02F8D40603193852D2E723) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `42c58b74` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0x9173C5A4aF659347e02933A48F48eAE9C7Df69c4` | ✅ | ✅ | +| Token | `0x9adF1B464aBC8E067dBa760825407eA53f197AB7` | ✅ | ✅ | +| Vault | `0xF00cCE0A6FB4FD94d3b0F5D7a309422FB55E9910` | ✅ | ✅ | +| Borrowing | `0xf6269D9F38E3b4F93f7e68F41D8ea06abe3Ef7b5` | ✅ | ✅ | +| Liquidation | `0x658D92670E33750598Db4f2f8A03a330B32f2B7F` | ✅ | ✅ | +| RiskManager | `0x2338cdA64BcBF632FdbC36757D6fCd1b5b16f209` | ✅ | ✅ | +| BalanceForwarder | `0x52b18F2Ea23b1bAcf8867eeF1af34916F942312F` | ✅ | ✅ | +| Governance | `0xEC475C94F6D0cee5210a31bf59794886E88C1654` | ✅ | ✅ | + +## EulerSwap V2 management implementation (unpacked from the implementation) + +EulerSwap delegatecalls management functions into a separate contract whose address is the public immutable `managementImpl`; it is verified from the same euler-swap pin. + +| Contract | Address | Bytecode | Embedded-immutable cross-check | +|----------|---------|----------|-------------------------------| +| EulerSwapManagement | `0xfC6701e4678Cd5A788BE59AFD874b5AACec122D1` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (EUL): + +Carries the Paladin-audited source revision (natspec blob) — byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`773453b1`](https://github.com/euler-xyz/euler-earn/tree/773453b1f4a6f1d27a1cd0c6d8f6ada572503b23) (eulerEarnFactory): + +src/ identical to the baseline (empty diff). + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) (eulerSwapV1Factory, eulerSwapV1Implementation, eulerSwapV1Periphery): + +Tag eulerswap-1.0 (official V1 release), descendant of the baseline. src delta: SPDX headers UNLICENSED→GPL (14 files) + PR #99 event hoisting (new Events.sol; hook emits Swap with sender). No state-machine or math changes. foundry optimizer_runs raised 10000→1000000 post-audit, pre-deployment. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..ce71a2c 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..39fe65b 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..1befa2e 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {Owned} from "solmate/src/auth/Owned.sol"; +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (eulOFTAdapter): + +Adapter files blob-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) (evc): + +Descendant of the baseline and the last commit ever to touch src/ on origin/master — the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers — proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding). + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultImplementation + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`f52cb43b`](https://github.com/euler-xyz/euler-price-oracle/tree/f52cb43b587c7fa90a7e722d52698003451feb62)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (rEUL): + +Component files byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (swapVerifier): + +Descendant of the baseline by 3 days (the merge adding the Enigma report PDF). src/Swaps delta is 100% non-semantic forge-fmt re-wrapping. This IS the Enigma-fixes-included state as deployed on 13 chains. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +index b70618d3..d210ab47 100644 +--- a/src/Swaps/MigrationHelper.sol ++++ b/src/Swaps/MigrationHelper.sol +@@ -95,10 +95,7 @@ contract MigrationHelper is EVCUtil { + /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. + /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying + /// the user's permit can only ever drain their own balance. +- function transferBalanceFromSender(address token, uint256 maxAmount, address to) +- external +- returns (uint256 amount) +- { ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) external returns (uint256 amount) { + amount = IERC20(token).balanceOf(_msgSender()); + if (amount > maxAmount) amount = maxAmount; + // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index 23a3c2fd..ec881e76 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -69,7 +69,8 @@ contract SwapVerifier is MigrationHelper { + /// @param receiver The address to transfer the asset to + /// @param amountMin The minimum amount of the asset that must be available before transfer + /// @param deadline A timestamp after which the transfer will revert +- /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if the minimum is met ++ /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if ++ /// the minimum is met + function verifyAmountMinAndTransfer(address asset, address receiver, uint256 amountMin, uint256 deadline) external { + if (deadline < block.timestamp) revert SwapVerifier_pastDeadline(); +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/137.md b/verify/137.md new file mode 100644 index 0000000..6cf6e56 --- /dev/null +++ b/verify/137.md @@ -0,0 +1,873 @@ +# Polygon — Deployed Code Verification + +Chain ID: 137 · Bytecode-proven: **10/10** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +**No attention items on this chain: every contract is bytecode-proven and matches or is reconciled to its audited baseline.** + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0x0dCA20a4…`](https://polygonscan.com/address/0x0dCA20a43aD0DC9B6fAccf22dAF6c3CEF70971D8) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `da5a2a71` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0x995C71de…`](https://polygonscan.com/address/0x995C71de11C1f07836ef7d09aC803340BDd91367) | [`evk-periphery@8c946bb1`](https://github.com/euler-xyz/evk-periphery/tree/8c946bb15574c764bee054de79758b958d0130d4) | ✅ `0b021e3f` | +1/−1 vs baseline | mint() gains 'virtual' (no behavior change) | +| eVaultFactory | [`0xB1771a13…`](https://polygonscan.com/address/0xB1771a13e2a13fCafA89B00335915E732B9466b7) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `3971bde2` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| eVaultImplementation | [`0xFac635be…`](https://polygonscan.com/address/0xFac635beB7d3B47d8E93B78ea6b43656Db84ffC8) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `8c001272` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0x90811Dac…`](https://polygonscan.com/address/0x90811DacA4BD23Fc79A87FBdff7522bED2d24B4B) | [`ethereum-vault-connector@912b301f`](https://github.com/euler-xyz/ethereum-vault-connector/tree/912b301f51301e586e5a7f09e48cf52bd52e9a0e) | ✅ `f4ec7203` | +69/−22 vs baseline | set-size 10→100 (audited) + hardening | +| oracleRouterFactory | [`0xbf5F8524…`](https://polygonscan.com/address/0xbf5F852416deEdFaBACb8B2699b4e8568F20D889) | [`evk-periphery@96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0xB7474ED2…`](https://polygonscan.com/address/0xB7474ED2418ee57976d5a22B3DE5aDed68867eBF) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `844a4ed8` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| rEUL | [`0xAB1ca795…`](https://polygonscan.com/address/0xAB1ca795DDcACa7DF9ec350a4adA727e8B7212Bd) | [`evk-periphery@8c946bb1`](https://github.com/euler-xyz/evk-periphery/tree/8c946bb15574c764bee054de79758b958d0130d4) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0xf52C9ef4…`](https://polygonscan.com/address/0xf52C9ef48d4510487aA107a36b24e37ae1269F71) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `83359e00` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| swapVerifier | [`0x2FD1d2B8…`](https://polygonscan.com/address/0x2FD1d2B8a7ea813240dBf8A157903034c4920c95) | [`evk-periphery@eae25d38`](https://github.com/euler-xyz/evk-periphery/tree/eae25d382bb58aaaaa9f1a3a55567af993ce32be) | ✅ `9469decd` | predates (+158/−34 audited later) | pre-refactor state (audit-pinned) | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0x1196EdD1312099Fa1A9aFFF8Aa3e46b9fDF1c205` | ✅ | ✅ | +| Token | `0xe485C2E0Ff4028c5e06BB4bC6ee8Dd7AB9A01527` | ✅ | ✅ | +| Vault | `0x4E90E10Bd7c2bE6f43Cca4F919F1795aDAFF47C8` | ✅ | ✅ | +| Borrowing | `0xC437b451a530C66B406E4369B3d37a09220eF887` | ✅ | ✅ | +| Liquidation | `0x3cF1382a61a273E3051E2265e23A20dbD1F48078` | ✅ | ✅ | +| RiskManager | `0xE257675640893BFAeD8EC48eF7E9C55021b00dCa` | ✅ | ✅ | +| BalanceForwarder | `0xfadb094D4dB022088b91B2afEC87353DC31fD97C` | ✅ | ✅ | +| Governance | `0x2B55aCC0d4E72353011114Ea956BEee0Cc3E25ca` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`8c946bb1`](https://github.com/euler-xyz/evk-periphery/tree/8c946bb15574c764bee054de79758b958d0130d4) (EUL): + +Post-2025-09 revision: delta vs baseline is the 'virtual' keyword on mint() (ERC20Synth enablement) — no behavior change. + +```diff +diff --git a/src/ERC20/deployed/ERC20BurnableMintable.sol b/src/ERC20/deployed/ERC20BurnableMintable.sol +index 82413624..19bb8e81 100644 +--- a/src/ERC20/deployed/ERC20BurnableMintable.sol ++++ b/src/ERC20/deployed/ERC20BurnableMintable.sol +@@ -45,7 +45,7 @@ contract ERC20BurnableMintable is AccessControlEnumerable, ERC20Burnable, ERC20P + /// @notice Mints new tokens and assigns them to an account + /// @param _account The address that will receive the minted tokens + /// @param _amount The amount of tokens to mint +- function mint(address _account, uint256 _amount) external onlyRole(MINTER_ROLE) { ++ function mint(address _account, uint256 _amount) external virtual onlyRole(MINTER_ROLE) { + _mint(_account, _amount); + } +``` + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`912b301f`](https://github.com/euler-xyz/ethereum-vault-connector/tree/912b301f51301e586e5a7f09e48cf52bd52e9a0e) (evc): + +Polygon-only deployment: the yaudit-evc-2026-setsize state (SET_MAX_ELEMENTS 10→100 for the Gondor/Polymarket integration; 0 C/H/M/L findings, informational fixes included via PR #203). Descendant of the baseline; its delta = the 14-chain pin's delta plus exactly the set-size audit scope. The branch remains unmerged to master by design. + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/Set.sol b/src/Set.sol +index a254b1e..9ae2944 100644 +--- a/src/Set.sol ++++ b/src/Set.sol +@@ -4,7 +4,7 @@ pragma solidity ^0.8.0; + + /// @dev Represents the maximum number of elements that can be stored in the set. + /// Must not exceed 255 due to the uint8 data type limit. +-uint8 constant SET_MAX_ELEMENTS = 10; ++uint8 constant SET_MAX_ELEMENTS = 100; + + /// @title ElementStorage + /// @notice This struct is used to store the value and stamp of an element. +diff --git a/src/interfaces/IEthereumVaultConnector.sol b/src/interfaces/IEthereumVaultConnector.sol +index 73cd28a..a8b2581 100644 +--- a/src/interfaces/IEthereumVaultConnector.sol ++++ b/src/interfaces/IEthereumVaultConnector.sol +@@ -214,8 +214,8 @@ interface IEVC { + /// @notice Enables a collateral for an account. + /// @dev A collaterals is a vault for which account's balances are under the control of the currently enabled + /// controller vault. Only the owner or an operator of the account can call this function. Unless it's a duplicate, +- /// the collateral is added to the end of the array. There can be at most 10 unique collaterals enabled at a time. +- /// Account status checks are performed. ++ /// the collateral is added to the end of the array. There can be at most SET_MAX_ELEMENTS (100) unique collaterals ++ /// enabled at a time. Account status checks are performed. + /// @param account The account address for which the collateral is being enabled. + /// @param vault The address being enabled as a collateral. + function enableCollateral(address account, address vault) external payable; +@@ -261,9 +261,9 @@ interface IEVC { + /// @notice Enables a controller for an account. + /// @dev A controller is a vault that has been chosen for an account to have special control over account’s + /// balances in the enabled collaterals vaults. Only the owner or an operator of the account can call this function. +- /// Unless it's a duplicate, the controller is added to the end of the array. Transiently, there can be at most 10 +- /// unique controllers enabled at a time, but at most one can be enabled after the outermost checks-deferrable +- /// call concludes. Account status checks are performed. ++ /// Unless it's a duplicate, the controller is added to the end of the array. Transiently, there can be at most ++ /// SET_MAX_ELEMENTS (100) unique controllers enabled at a time, but at most one can be enabled after the outermost ++ /// checks-deferrable call concludes. Account status checks are performed. + /// @param account The address for which the controller is being enabled. + /// @param vault The address of the controller being enabled. + function enableController(address account, address vault) external payable; +@@ -394,9 +394,9 @@ interface IEVC { + + /// @notice Checks the status of an account and reverts if it is not valid. + /// @dev If checks deferred, the account is added to the set of accounts to be checked at the end of the outermost +- /// checks-deferrable call. There can be at most 10 unique accounts added to the set at a time. Account status +- /// check is performed by calling into the selected controller vault and passing the array of currently enabled +- /// collaterals. If controller is not selected, the account is always considered valid. ++ /// checks-deferrable call. There can be at most SET_MAX_ELEMENTS (100) unique accounts added to the set at a time. ++ /// Account status check is performed by calling into the selected controller vault and passing the array of ++ /// currently enabled collaterals. If controller is not selected, the account is always considered valid. + /// @param account The address of the account to be checked. + function requireAccountStatusCheck(address account) external payable; + +@@ -415,8 +415,8 @@ interface IEVC { + + /// @notice Checks the status of a vault and reverts if it is not valid. + /// @dev If checks deferred, the vault is added to the set of vaults to be checked at the end of the outermost +- /// checks-deferrable call. There can be at most 10 unique vaults added to the set at a time. This function can +- /// only be called by the vault itself. ++ /// checks-deferrable call. There can be at most SET_MAX_ELEMENTS (100) unique vaults added to the set at a time. ++ /// This function can only be called by the vault itself. + function requireVaultStatusCheck() external payable; + + /// @notice Forgives previously deferred vault status check. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultFactory, eVaultImplementation, protocolConfig, sequenceRegistry + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`f52cb43b`](https://github.com/euler-xyz/euler-price-oracle/tree/f52cb43b587c7fa90a7e722d52698003451feb62)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`8c946bb1`](https://github.com/euler-xyz/evk-periphery/tree/8c946bb15574c764bee054de79758b958d0130d4) (rEUL): + +Component files byte-identical to the baseline (pin = current origin/master tip). + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`eae25d38`](https://github.com/euler-xyz/evk-periphery/tree/eae25d382bb58aaaaa9f1a3a55567af993ce32be) (swapVerifier): + +> **This deployment predates the component baseline.** Its own audited anchor is [BailSec (`bailsec-evk-periphery-auxiliary-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/BailSec%20EVK%20Periphery%20Oracle%20Hook%20SwapVerifier.pdf): BailSec's March-2026 scope table pins SwapVerifier.sol at EXACTLY this commit (sole SwapVerifier finding: one acknowledged informational). The pin also contains the yaudit-swapverifier-update-2026 fix (b6046f44, cited verbatim in that report), so it is a doubly audit-pinned state. The pin→baseline delta is precisely the Enigma-Dark-reviewed refactor: TransferFromSender folded into the new MigrationHelper parent, with no logic change to the verify functions. +> +> The diff below therefore reads pin→baseline: it shows the audited changes this deployment predates, not unreviewed drift. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +new file mode 100644 +index 00000000..b70618d3 +--- /dev/null ++++ b/src/Swaps/MigrationHelper.sol +@@ -0,0 +1,153 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++pragma solidity ^0.8.0; ++ ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; ++import {SafeERC20Permit2Lib} from "euler-earn/libraries/SafeERC20Permit2Lib.sol"; ++import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; ++ ++/// @notice Minimal Aave V3 Pool interface used for position migrations. ++interface IAaveV3Pool { ++ function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) ++ external; ++} ++ ++/// @notice Minimal Morpho Blue interface used for position migrations. ++interface IMorpho { ++ struct MarketParams { ++ address loanToken; ++ address collateralToken; ++ address oracle; ++ address irm; ++ uint256 lltv; ++ } ++ ++ function borrow( ++ MarketParams calldata marketParams, ++ uint256 assets, ++ uint256 shares, ++ address onBehalf, ++ address receiver ++ ) external returns (uint256 assetsBorrowed, uint256 sharesBorrowed); ++ ++ function withdrawCollateral(MarketParams calldata marketParams, uint256 assets, address onBehalf, address receiver) ++ external; ++} ++ ++/// @title MigrationHelper ++/// @custom:security-contact security@euler.xyz ++/// @author Euler Labs (https://www.eulerlabs.com/) ++/// @notice Pulls tokens, and performs debt- and collateral-bearing actions on external lending protocols ++/// (Aave V3, Morpho Blue), on behalf of the EVC-authenticated sender. Used both as a gas-saving ++/// allowance sink for swaps and for migrating positions in and out of Euler. ++/// @dev This contract is trusted and can safely receive token allowances, Aave credit delegations and ++/// Morpho operator authorizations from users. Security model: every state-changing function pins the ++/// token source / protocol-side on-behalf account to the EVC-authenticated `_msgSender()`. A user ++/// grants this contract a standing allowance / credit delegation / operator authorization so a batch ++/// can act for them, but because the acting account is bound to that caller, the grant can only ever ++/// be exercised on the granting user's own position; a front-runner who replays the user's ++/// permit/delegation/authorization signature is authenticated as themselves and can only touch their ++/// own balance/position. `_msgSender()` resolves to the EVC on-behalf-of account, so an address the ++/// user has authorized as an EVC operator can likewise exercise these grants on the user's behalf — a ++/// consequence of the user's own operator authorization, consistent with the rest of the swap periphery. ++/// CAUTION: this means a *standing* Aave credit delegation or Morpho operator authorization left on this ++/// contract is exercisable by ANY EVC operator the user has authorized (for any unrelated reason): such an ++/// operator can borrow the user's delegated credit / withdraw their external collateral and direct the ++/// proceeds to themselves, bounded only by the external protocol's own health checks. The `_msgSender()` ++/// binding protects against third parties and replayers, not against the user's own operators. The Aave ++/// credit delegation / Morpho operator authorization should therefore be granted and revoked within the ++/// migration batch rather than left standing. The contract custodies no funds across calls, and safety ++/// does not depend on the `token`/`pool`/`morpho` arguments being canonical addresses. ++contract MigrationHelper is EVCUtil { ++ using SafeERC20 for IERC20; ++ ++ /// @notice Address of Permit2 contract ++ address public immutable permit2; ++ ++ /// @dev Aave V3 variable interest rate mode. Stable-rate borrowing is not supported. ++ uint256 internal constant AAVE_VARIABLE_RATE_MODE = 2; ++ ++ /// @notice Contract constructor ++ /// @param _evc Address of the EthereumVaultConnector contract ++ /// @param _permit2 Address of the Permit2 contract ++ constructor(address _evc, address _permit2) EVCUtil(_evc) { ++ permit2 = _permit2; ++ } ++ ++ /// @notice Pull tokens from sender to the designated receiver ++ /// @param token ERC20 token address ++ /// @param amount Amount of the token to transfer ++ /// @param to Receiver of the token ++ function transferFromSender(address token, uint256 amount, address to) public { ++ SafeERC20Permit2Lib.safeTransferFromWithPermit2(IERC20(token), _msgSender(), to, amount, permit2); ++ } ++ ++ /// @notice Pull the sender's entire live balance of a token, capped at `maxAmount`, and forward it to `to` ++ /// @param token The (possibly rebasing) ERC20 token to pull, e.g. an Aave aToken ++ /// @param maxAmount Upper bound on the amount to pull; the actual amount is min(balance, maxAmount) ++ /// @param to Recipient of the pulled tokens (e.g. the Swapper) ++ /// @return amount The amount actually transferred ++ /// @dev Reading the live balance avoids leaving dust behind when the token rebases (e.g. an Aave ++ /// aToken accruing interest between the user signing the permit and the batch executing), so the ++ /// whole position can be drained without an exact off-chain amount. ++ /// @dev `maxAmount` bounds the pull to the balance measured off-chain plus a small accrual buffer: an ++ /// unexpectedly large balance, or a larger pre-existing allowance, can never cause an over-pull. ++ /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. ++ /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying ++ /// the user's permit can only ever drain their own balance. ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) ++ external ++ returns (uint256 amount) ++ { ++ amount = IERC20(token).balanceOf(_msgSender()); ++ if (amount > maxAmount) amount = maxAmount; ++ // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. ++ if (amount == 0) return 0; ++ transferFromSender(token, amount, to); ++ } ++ ++ /// @notice Borrow an asset from Aave V3 on behalf of the sender and forward it to a receiver ++ /// @param pool Address of the Aave V3 Pool ++ /// @param asset The reserve asset to borrow ++ /// @param amount The amount of `asset` to borrow ++ /// @param to Recipient of the borrowed assets (e.g. the Swapper) ++ /// @dev The sender must have granted variable-debt credit delegation to this contract for `asset`. ++ /// @dev Aave sends the borrowed assets to msg.sender (this contract); only the amount actually ++ /// received from the borrow (the balance delta) is forwarded to `to`, so a non-canonical or ++ /// no-op `pool` cannot cause any pre-existing balance to be paid out, and no balance is left behind. ++ function aaveBorrowForSender(address pool, address asset, uint256 amount, address to) external { ++ uint256 balanceBefore = IERC20(asset).balanceOf(address(this)); ++ IAaveV3Pool(pool).borrow(asset, amount, AAVE_VARIABLE_RATE_MODE, 0, _msgSender()); ++ IERC20(asset).safeTransfer(to, IERC20(asset).balanceOf(address(this)) - balanceBefore); ++ } ++ ++ /// @notice Withdraw Morpho Blue collateral on behalf of the sender, directly to a receiver ++ /// @param morpho Address of the Morpho Blue contract ++ /// @param marketParams The Morpho market parameters identifying the position ++ /// @param amount The amount of collateral to withdraw ++ /// @param to Recipient of the withdrawn collateral (e.g. the Swapper) ++ /// @dev The sender must have authorized this contract as a Morpho operator. ++ function morphoWithdrawCollateralForSender( ++ address morpho, ++ IMorpho.MarketParams calldata marketParams, ++ uint256 amount, ++ address to ++ ) external { ++ IMorpho(morpho).withdrawCollateral(marketParams, amount, _msgSender(), to); ++ } ++ ++ /// @notice Borrow from a Morpho Blue market on behalf of the sender, directly to a receiver ++ /// @param morpho Address of the Morpho Blue contract ++ /// @param marketParams The Morpho market parameters identifying the market ++ /// @param amount The amount of loan asset to borrow ++ /// @param to Recipient of the borrowed assets (e.g. the Swapper) ++ /// @dev The sender must have authorized this contract as a Morpho operator. ++ function morphoBorrowForSender( ++ address morpho, ++ IMorpho.MarketParams calldata marketParams, ++ uint256 amount, ++ address to ++ ) external { ++ IMorpho(morpho).borrow(marketParams, amount, 0, _msgSender(), to); ++ } ++} +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index a05a0d84..23a3c2fd 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -3,16 +3,17 @@ + pragma solidity ^0.8.0; + + import {IEVault} from "evk/EVault/IEVault.sol"; +-import {TransferFromSender} from "./TransferFromSender.sol"; ++import {MigrationHelper} from "./MigrationHelper.sol"; + import {IEVault, IERC4626} from "evk/EVault/IEVault.sol"; + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SwapVerifier + /// @custom:security-contact security@euler.xyz + /// @author Euler Labs (https://www.eulerlabs.com/) +-/// @notice Simple contract used to verify post swap conditions. Includes TransferFromSender helper for gas savings. ++/// @notice Simple contract used to verify post swap conditions. Inherits the MigrationHelper from-sender ++/// helpers (transferFromSender and position migration primitives) for gas savings. + /// @dev This contract is the only trusted code in the EVK swap periphery +-contract SwapVerifier is TransferFromSender { ++contract SwapVerifier is MigrationHelper { + error SwapVerifier_skimMin(); + error SwapVerifier_depositMin(); + error SwapVerifier_transferMin(); +@@ -22,7 +23,7 @@ contract SwapVerifier is TransferFromSender { + /// @notice Contract constructor + /// @param evc Address of the EthereumVaultConnector contract + /// @param permit2 Address of the Permit2 contract +- constructor(address evc, address permit2) TransferFromSender(evc, permit2) {} ++ constructor(address evc, address permit2) MigrationHelper(evc, permit2) {} + + /// @notice Verify results of a regular swap, when bought tokens are sent to the vault and skim for the buyer + /// @param vault The EVault to query +diff --git a/src/Swaps/TransferFromSender.sol b/src/Swaps/TransferFromSender.sol +deleted file mode 100644 +index 01ab58ef..00000000 +--- a/src/Swaps/TransferFromSender.sol ++++ /dev/null +@@ -1,30 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +- +-pragma solidity ^0.8.0; +- +-import {SafeERC20Permit2Lib, IERC20} from "euler-earn/libraries/SafeERC20Permit2Lib.sol"; +-import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +- +-/// @title TransferFromSender +-/// @custom:security-contact security@euler.xyz +-/// @author Euler Labs (https://www.eulerlabs.com/) +-/// @notice Simple contract used to pull tokens from the sender. +-/// @dev This contract is trusted and can safely receive allowance on token transfers from users. +-contract TransferFromSender is EVCUtil { +- /// @notice Address of Permit2 contract +- address public immutable permit2; +- +- /// @notice Contract constructor +- /// @param _permit2 Address of the Permit2 contract +- constructor(address _evc, address _permit2) EVCUtil(_evc) { +- permit2 = _permit2; +- } +- +- /// @notice Pull tokens from sender to the designated receiver +- /// @param token ERC20 token address +- /// @param amount Amount of the token to transfer +- /// @param to Receiver of the token +- function transferFromSender(address token, uint256 amount, address to) public { +- SafeERC20Permit2Lib.safeTransferFromWithPermit2(IERC20(token), _msgSender(), to, amount, permit2); +- } +-} +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/143.md b/verify/143.md new file mode 100644 index 0000000..41a375b --- /dev/null +++ b/verify/143.md @@ -0,0 +1,1436 @@ +# Monad — Deployed Code Verification + +Chain ID: 143 · Bytecode-proven: **16/16** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +**No attention items on this chain: every contract is bytecode-proven and matches or is reconciled to its audited baseline.** + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0xa231DccE…`](https://monadvision.com/address/0xa231DccE58EA5A43E69EF351D89ea4212Ec0f30b) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `47294620` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0xDef72Af3…`](https://monadvision.com/address/0xDef72Af3fc69E1Dd5a094f7DDa08Ba203CD0438B) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `0b021e3f` | ≡ baseline | — | +| eulOFTAdapter | [`0x831257BF…`](https://monadvision.com/address/0x831257BFa5478111d2327e08c4068ec37Ac14B81) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `1036d1c0` | ≡ baseline | — | +| eVaultFactory | [`0xba4Dd672…`](https://monadvision.com/address/0xba4Dd672062dE8FeeDb665DD4410658864483f1E) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0xef17750D…`](https://monadvision.com/address/0xef17750D3a162E28a302E266c474ff8989d60ECD) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `8c001272` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0x7a9324E8…`](https://monadvision.com/address/0x7a9324E8f270413fa2E458f5831226d99C7477CD) | [`ethereum-vault-connector@a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) | ✅ `b12f6d72` | +58/−11 vs baseline | EVCUtil helper + signer-exclusion hardening | +| oracleRouterFactory | [`0xdDA3cBC1…`](https://monadvision.com/address/0xdDA3cBC18e90606A83FBae6F798991af06dFA902) | [`evk-periphery@96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0x94A2d1d1…`](https://monadvision.com/address/0x94A2d1d175F1d828935a374091e2009CF1cED858) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0xff074349…`](https://monadvision.com/address/0xff074349C8b89bB7362bD25c58742896D817A862) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0x39F81037…`](https://monadvision.com/address/0x39F81037f20AC6068CbCd30f748094c58bfE7d7b) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0x24a00DaB…`](https://monadvision.com/address/0x24a00DaB8a85e70B59Cd03B4250Db80Fcd30bE5f) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `2fc2cdd1` | +3/−5 vs baseline | formatting only | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0xF463d4Ac…`](https://monadvision.com/address/0xF463d4Acb650cc6C4E1D6cD4D0d1b0cb224094cF) | [`euler-earn@bece7172`](https://github.com/euler-xyz/euler-earn/tree/bece7172a87551e6943a52b08c9a0117eb02c6c3) | ✅ `c65c6dcf` | +18/−18 vs baseline | import-path style only | +| eulerEarnPublicAllocator | [`0x65A66F24…`](https://monadvision.com/address/0x65A66F24a25E8CF651C9e31D296623298C80F742) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV1Factory | [`0x34f8F028…`](https://monadvision.com/address/0x34f8F028C6a446A464c10a135F44Fc6fB2CEe1A9) | [`euler-swap@5d270c76`](https://github.com/euler-xyz/euler-swap/tree/5d270c764204b896770e967c22c7b95959bf6660) | ✅ `7c9a247e` | +53/−30 vs baseline | licenses/events + natspec, import fix | +| eulerSwapV1Implementation | [`0xBFD5C7bb…`](https://monadvision.com/address/0xBFD5C7bb1C208FEc761284Af7dB6fF1F4314372c) | [`euler-swap@5d270c76`](https://github.com/euler-xyz/euler-swap/tree/5d270c764204b896770e967c22c7b95959bf6660) | ✅ `20cae9a4` | +53/−30 vs baseline | licenses/events + natspec, import fix | +| eulerSwapV1Periphery | [`0xd1F69cf9…`](https://monadvision.com/address/0xd1F69cf959c1a3AAe7BEE5ec677222d259585B27) | [`euler-swap@98c05c56`](https://github.com/euler-xyz/euler-swap/tree/98c05c56f7722887d293ef231accd689c2ea2493) | ✅ `703cfc72` | +56/−30 vs baseline | licenses/events + natspec/formatting | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0xe49B8B21f28Ee16136d852661870Df05c59717CE` | ✅ | ✅ | +| Token | `0xaca7c91684ed0E30717c4Cd0F5Ee1BD9bAF2A454` | ✅ | ✅ | +| Vault | `0x053F25b25A924Bee8246caC29Dab96Df92BdacDC` | ✅ | ✅ | +| Borrowing | `0xe0d210a129aA659569D69dD8869f80ba03BB4AE4` | ✅ | ✅ | +| Liquidation | `0x2b6B96806A4741C29Ea08144C853937c3737355c` | ✅ | ✅ | +| RiskManager | `0xcd1e576e5D19E39809f668b9d2039F23938F944a` | ✅ | ✅ | +| BalanceForwarder | `0xa0a08f72c232f0447F4B3C8638893343d8312543` | ✅ | ✅ | +| Governance | `0x20dD95718d078d536A5243260fdDc915a6CbB75a` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (EUL): + +Carries the Paladin-audited source revision (natspec blob) — byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`bece7172`](https://github.com/euler-xyz/euler-earn/tree/bece7172a87551e6943a52b08c9a0117eb02c6c3) (eulerEarnFactory): + +Monad/Morph deployments: public euler-earn master commit (“fix: absolute import paths”, 2025-10-14); descendant of the baseline with import-path-style deltas only. Compiled at the repo profile (0.8.26, runs 200, via_ir) with the deploy workspace’s OpenZeppelin v5.1.0. + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`5d270c76`](https://github.com/euler-xyz/euler-swap/tree/5d270c764204b896770e967c22c7b95959bf6660) (eulerSwapV1Factory, eulerSwapV1Implementation): + +Monad factory/implementation pin; descendant of eulerswap-1.0 on linear master. Adds natspec-only named returns + a solmate import-path remapping fix. Zero semantic change. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..4e1541d 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +@@ -56,7 +56,9 @@ interface IEulerSwap { + returns (uint256); + + /// @notice Upper-bounds on the amounts of each token that this pool can currently support swaps for. +- function getLimits(address tokenIn, address tokenOut) external view returns (uint256, uint256); ++ /// @return limitIn Max amount of `tokenIn` that can be sold. ++ /// @return limitOut Max amount of `tokenOut` that can be bought. ++ function getLimits(address tokenIn, address tokenOut) external view returns (uint256 limitIn, uint256 limitOut); + + /// @notice Optimistically sends the requested amounts of tokens to the `to` + /// address, invokes `eulerSwapCall` callback on `to` (if `data` was provided), +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..e2522dd 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +@@ -40,6 +40,8 @@ interface IEulerSwapPeriphery { + view + returns (uint256); + +- /// @notice Upper-bound on the max amount that can be sold of tokenIn and bought of tokenOut +- function getLimits(address eulerSwap, address tokenIn, address tokenOut) external view returns (uint256, uint256); ++ /// @notice Upper-bounds on the amounts of each token that this pool can currently support swaps for. ++ /// @return limitIn Max amount of `tokenIn` that can be sold. ++ /// @return limitOut Max amount of `tokenOut` that can be bought. ++ function getLimits(address eulerSwap, address tokenIn, address tokenOut) external view returns (uint256 limitIn, uint256 limitOut); + } +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..2f55f28 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,7 +1,7 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + +-import {Owned} from "solmate/src/auth/Owned.sol"; ++import {Owned} from "solmate/auth/Owned.sol"; + import {UniswapHook} from "../UniswapHook.sol"; + import {IPoolManager} from "v4-core/interfaces/IPoolManager.sol"; +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`98c05c56`](https://github.com/euler-xyz/euler-swap/tree/98c05c56f7722887d293ef231accd689c2ea2493) (eulerSwapV1Periphery): + +Monad periphery pin; descendant of 5d270c76. Adds one forge-fmt line-wrap. Zero semantic change. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..4e1541d 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +@@ -56,7 +56,9 @@ interface IEulerSwap { + returns (uint256); + + /// @notice Upper-bounds on the amounts of each token that this pool can currently support swaps for. +- function getLimits(address tokenIn, address tokenOut) external view returns (uint256, uint256); ++ /// @return limitIn Max amount of `tokenIn` that can be sold. ++ /// @return limitOut Max amount of `tokenOut` that can be bought. ++ function getLimits(address tokenIn, address tokenOut) external view returns (uint256 limitIn, uint256 limitOut); + + /// @notice Optimistically sends the requested amounts of tokens to the `to` + /// address, invokes `eulerSwapCall` callback on `to` (if `data` was provided), +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..944a4ad 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +@@ -40,6 +40,11 @@ interface IEulerSwapPeriphery { + view + returns (uint256); + +- /// @notice Upper-bound on the max amount that can be sold of tokenIn and bought of tokenOut +- function getLimits(address eulerSwap, address tokenIn, address tokenOut) external view returns (uint256, uint256); ++ /// @notice Upper-bounds on the amounts of each token that this pool can currently support swaps for. ++ /// @return limitIn Max amount of `tokenIn` that can be sold. ++ /// @return limitOut Max amount of `tokenOut` that can be bought. ++ function getLimits(address eulerSwap, address tokenIn, address tokenOut) ++ external ++ view ++ returns (uint256 limitIn, uint256 limitOut); + } +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..2f55f28 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,7 +1,7 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + +-import {Owned} from "solmate/src/auth/Owned.sol"; ++import {Owned} from "solmate/auth/Owned.sol"; + import {UniswapHook} from "../UniswapHook.sol"; + import {IPoolManager} from "v4-core/interfaces/IPoolManager.sol"; +``` + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (eulOFTAdapter): + +Adapter files blob-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) (evc): + +Descendant of the baseline and the last commit ever to touch src/ on origin/master — the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers — proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding). + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultImplementation + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`f52cb43b`](https://github.com/euler-xyz/euler-price-oracle/tree/f52cb43b587c7fa90a7e722d52698003451feb62)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (rEUL): + +Component files byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (swapVerifier): + +Descendant of the baseline by 3 days (the merge adding the Enigma report PDF). src/Swaps delta is 100% non-semantic forge-fmt re-wrapping. This IS the Enigma-fixes-included state as deployed on 13 chains. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +index b70618d3..d210ab47 100644 +--- a/src/Swaps/MigrationHelper.sol ++++ b/src/Swaps/MigrationHelper.sol +@@ -95,10 +95,7 @@ contract MigrationHelper is EVCUtil { + /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. + /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying + /// the user's permit can only ever drain their own balance. +- function transferBalanceFromSender(address token, uint256 maxAmount, address to) +- external +- returns (uint256 amount) +- { ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) external returns (uint256 amount) { + amount = IERC20(token).balanceOf(_msgSender()); + if (amount > maxAmount) amount = maxAmount; + // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index 23a3c2fd..ec881e76 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -69,7 +69,8 @@ contract SwapVerifier is MigrationHelper { + /// @param receiver The address to transfer the asset to + /// @param amountMin The minimum amount of the asset that must be available before transfer + /// @param deadline A timestamp after which the transfer will revert +- /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if the minimum is met ++ /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if ++ /// the minimum is met + function verifyAmountMinAndTransfer(address asset, address receiver, uint256 amountMin, uint256 deadline) external { + if (deadline < block.timestamp) revert SwapVerifier_pastDeadline(); +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/146.md b/verify/146.md new file mode 100644 index 0000000..01c26a1 --- /dev/null +++ b/verify/146.md @@ -0,0 +1,1070 @@ +# Sonic — Deployed Code Verification + +Chain ID: 146 · Bytecode-proven: **21/21** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0xe6E4687C…`](https://sonicscan.org/address/0xe6E4687C35429942391AfE42CDdECba857531492) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `47294620` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0x8e15C8D3…`](https://sonicscan.org/address/0x8e15C8D399e86d4FD7B427D42f06c60cDD9397e7) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `0b021e3f` | ≡ baseline | — | +| eulOFTAdapter | [`0x31aA7423…`](https://sonicscan.org/address/0x31aA74232A0b0E50e5bF95780b2116710a34c7E9) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `1036d1c0` | ≡ baseline | — | +| eVaultFactory | [`0xF075cC86…`](https://sonicscan.org/address/0xF075cC8660B51D0b8a4474e3f47eDAC5fA034cFB) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0x11f95aaa…`](https://sonicscan.org/address/0x11f95aaa59F1AD89576c61E3C9Cd24DF1FdCF46f) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `8c001272` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0x4860C903…`](https://sonicscan.org/address/0x4860C903f6Ad709c3eDA46D3D502943f184D4315) | [`ethereum-vault-connector@a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) | ✅ `b12f6d72` | +58/−11 vs baseline | EVCUtil helper + signer-exclusion hardening | +| oracleRouterFactory | [`0xc5b9B95a…`](https://sonicscan.org/address/0xc5b9B95a769C24c18c344c2659db61a0AdFB736E) | [`evk-periphery@96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0xc2f9FE90…`](https://sonicscan.org/address/0xc2f9FE90bd17e017898b6EfDaa73c34Fddde299e) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0x09E6cab4…`](https://sonicscan.org/address/0x09E6cab47B7199b9d3839A2C40654f246d518a80) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0x6F417AaE…`](https://sonicscan.org/address/0x6F417AaEc1D41dB692307269acDA019Ce5F10b0e) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0xbD0d0Fe1…`](https://sonicscan.org/address/0xbD0d0Fe1D6F655Aad80b360f46390d876f2d278f) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `2fc2cdd1` | +3/−5 vs baseline | formatting only | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0x3397ec7d…`](https://sonicscan.org/address/0x3397ec7d28cF645A017869Fe4B41c75f5B0b75a8) | [`euler-earn@773453b1`](https://github.com/euler-xyz/euler-earn/tree/773453b1f4a6f1d27a1cd0c6d8f6ada572503b23) | ✅ `c9ee150e` | ≡ baseline | — | +| eulerEarnPublicAllocator | [`0x82b27b52…`](https://sonicscan.org/address/0x82b27b528DA0516E653e02e5f870853d22Cbc6Df) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV1Factory | [`0x94041db6…`](https://sonicscan.org/address/0x94041db6deC15f79666B07846c13e6F7341b4a80) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `7c9a247e` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Implementation | [`0x4D57F545…`](https://sonicscan.org/address/0x4D57F54582b333E4184A3cF40d1D61FE6D70c35D) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `20cae9a4` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Periphery | [`0xb2237DC8…`](https://sonicscan.org/address/0xb2237DC86B184e50Fc2F8b028B2b7AE192ef2566) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `703cfc72` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV2Factory | [`0x46D23b2d…`](https://sonicscan.org/address/0x46D23b2d948b159859A5BB9C96c3190F4b43Ebb6) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `4bdd5d47` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0x1C266a98…`](https://sonicscan.org/address/0x1C266a986B6AfA7EbA68263c5323a0bF0fe4F2a4) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `408124d9` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0x4e4e5246…`](https://sonicscan.org/address/0x4e4e524613d840D2D30B694F363b5b1931e82A75) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `f98bd760` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0x8653d1B5…`](https://sonicscan.org/address/0x8653d1B50AA6adaaD64Dc140588dBC8c11141581) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `83e2e2c4` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0x0601a383…`](https://sonicscan.org/address/0x0601a38324D3cde22EBD531c799Ad318a6B8CF93) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `42c58b74` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0xc11085f6F3BA3C685502C8a99669240e8e450a20` | ✅ | ✅ | +| Token | `0x6B0d4eFa46bc7F8f17E9b1aa30132d426907eBe1` | ✅ | ✅ | +| Vault | `0x8D089d7B8af57Be845ff79cF51288f716Ff9C945` | ✅ | ✅ | +| Borrowing | `0xf6fc02BfeF0E901B50657Dc64Ff1506D1f331fDD` | ✅ | ✅ | +| Liquidation | `0xCEC866898D475F32CbE74ab9cb76448A6b557bc3` | ✅ | ✅ | +| RiskManager | `0x3D6FFa08A81d6C6f506733A6Cb8C264c1585d134` | ✅ | ✅ | +| BalanceForwarder | `0x65f7d2208e7Ac3c19AF7e48643FEE1CC0533588F` | ✅ | ✅ | +| Governance | `0x3E9c05d9e384B18cd964e52B1fe232bcfDD19625` | ✅ | ✅ | + +## EulerSwap V2 management implementation (unpacked from the implementation) + +EulerSwap delegatecalls management functions into a separate contract whose address is the public immutable `managementImpl`; it is verified from the same euler-swap pin. + +| Contract | Address | Bytecode | Embedded-immutable cross-check | +|----------|---------|----------|-------------------------------| +| EulerSwapManagement | `0xec54CD8b27Db6e1c070BcB392BD8cD1217c1647a` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (EUL): + +Carries the Paladin-audited source revision (natspec blob) — byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`773453b1`](https://github.com/euler-xyz/euler-earn/tree/773453b1f4a6f1d27a1cd0c6d8f6ada572503b23) (eulerEarnFactory): + +src/ identical to the baseline (empty diff). + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) (eulerSwapV1Factory, eulerSwapV1Implementation, eulerSwapV1Periphery): + +Tag eulerswap-1.0 (official V1 release), descendant of the baseline. src delta: SPDX headers UNLICENSED→GPL (14 files) + PR #99 event hoisting (new Events.sol; hook emits Swap with sender). No state-machine or math changes. foundry optimizer_runs raised 10000→1000000 post-audit, pre-deployment. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..ce71a2c 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..39fe65b 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..1befa2e 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {Owned} from "solmate/src/auth/Owned.sol"; +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (eulOFTAdapter): + +Adapter files blob-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) (evc): + +Descendant of the baseline and the last commit ever to touch src/ on origin/master — the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers — proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding). + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultImplementation + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`f52cb43b`](https://github.com/euler-xyz/euler-price-oracle/tree/f52cb43b587c7fa90a7e722d52698003451feb62)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (rEUL): + +Component files byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (swapVerifier): + +Descendant of the baseline by 3 days (the merge adding the Enigma report PDF). src/Swaps delta is 100% non-semantic forge-fmt re-wrapping. This IS the Enigma-fixes-included state as deployed on 13 chains. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +index b70618d3..d210ab47 100644 +--- a/src/Swaps/MigrationHelper.sol ++++ b/src/Swaps/MigrationHelper.sol +@@ -95,10 +95,7 @@ contract MigrationHelper is EVCUtil { + /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. + /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying + /// the user's permit can only ever drain their own balance. +- function transferBalanceFromSender(address token, uint256 maxAmount, address to) +- external +- returns (uint256 amount) +- { ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) external returns (uint256 amount) { + amount = IERC20(token).balanceOf(_msgSender()); + if (amount > maxAmount) amount = maxAmount; + // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index 23a3c2fd..ec881e76 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -69,7 +69,8 @@ contract SwapVerifier is MigrationHelper { + /// @param receiver The address to transfer the asset to + /// @param amountMin The minimum amount of the asset that must be available before transfer + /// @param deadline A timestamp after which the transfer will revert +- /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if the minimum is met ++ /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if ++ /// the minimum is met + function verifyAmountMinAndTransfer(address asset, address receiver, uint256 amountMin, uint256 deadline) external { + if (deadline < block.timestamp) revert SwapVerifier_pastDeadline(); +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/1923.md b/verify/1923.md new file mode 100644 index 0000000..c329b0e --- /dev/null +++ b/verify/1923.md @@ -0,0 +1,1272 @@ +# Swell — Deployed Code Verification + +Chain ID: 1923 · Bytecode-proven: **21/21** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0x9fb7215e…`](https://explorer.swellnetwork.io/address/0x9fb7215ef6297498D6807caf9f3aC8BA3154db29) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `48762e01` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0x80ccFBec…`](https://explorer.swellnetwork.io/address/0x80ccFBec4b8c82265abdc226Ad3Df84C0726E7A3) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `0b021e3f` | ≡ baseline | — | +| eulOFTAdapter | [`0xD0148dDB…`](https://explorer.swellnetwork.io/address/0xD0148dDB69f4d8182Ef863d6f81ED6519D8c83a2) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `1036d1c0` | ≡ baseline | — | +| eVaultFactory | [`0x238bF86b…`](https://explorer.swellnetwork.io/address/0x238bF86bb451ec3CA69BB855f91BDA001aB118b9) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0x70f12862…`](https://explorer.swellnetwork.io/address/0x70f1286239228B28A047c727C2df390045299486) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `8c001272` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0x08739CBe…`](https://explorer.swellnetwork.io/address/0x08739CBede6E28E387685ba20e6409bD16969Cde) | [`ethereum-vault-connector@a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) | ✅ `b12f6d72` | +58/−11 vs baseline | EVCUtil helper + signer-exclusion hardening | +| oracleRouterFactory | [`0x0135fC26…`](https://explorer.swellnetwork.io/address/0x0135fC2605ff2C89E550C2d4C7d75068A4782B43) | [`evk-periphery@96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0x6682Af28…`](https://explorer.swellnetwork.io/address/0x6682Af2820633067A1de5bE99b2DCb2d38F1e241) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0x021694af…`](https://explorer.swellnetwork.io/address/0x021694af083d67950Ac994E63e0a70C30D913836) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0xC4589C61…`](https://explorer.swellnetwork.io/address/0xC4589C6199516F96B422D91020563Fe65b28918e) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0x605280f2…`](https://explorer.swellnetwork.io/address/0x605280f2F939255Ab36FaFdBC654dE3cfbD5c616) | [`evk-periphery@eae25d38`](https://github.com/euler-xyz/evk-periphery/tree/eae25d382bb58aaaaa9f1a3a55567af993ce32be) | ✅ `9469decd` | predates (+158/−34 audited later) | pre-refactor state (audit-pinned) | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0x3073e1B4…`](https://explorer.swellnetwork.io/address/0x3073e1B42f8Cc933f2d678DdA10acDE51F4E49a3) | [`euler-earn@773453b1`](https://github.com/euler-xyz/euler-earn/tree/773453b1f4a6f1d27a1cd0c6d8f6ada572503b23) | ✅ `c9ee150e` | ≡ baseline | — | +| eulerEarnPublicAllocator | [`0x0a13C9fc…`](https://explorer.swellnetwork.io/address/0x0a13C9fc4613Cae202138F4E1C2b9125A20562E8) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV1Factory | [`0x976dd856…`](https://explorer.swellnetwork.io/address/0x976dd85654B3b2f9fb66280ACE30Cab7C81a2130) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `7c9a247e` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Implementation | [`0x3620dAb0…`](https://explorer.swellnetwork.io/address/0x3620dAb0DB5595479a4D5408595D48FbE48CeA2A) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `20cae9a4` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Periphery | [`0x34932C04…`](https://explorer.swellnetwork.io/address/0x34932C04c3d27c2BD7aCd0B5d203bfd65a17f481) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `703cfc72` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV2Factory | [`0x980cd01d…`](https://explorer.swellnetwork.io/address/0x980cd01dB708C2B008cF8076aa856fcAeF60698c) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `4bdd5d47` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0xCB728171…`](https://explorer.swellnetwork.io/address/0xCB72817170a9d0f136fcB764f55BEEC638C25acb) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `408124d9` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0x74F7726e…`](https://explorer.swellnetwork.io/address/0x74F7726eF6D8107403a6c581B985D27ED0561f9D) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `f98bd760` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0x6FB6C91e…`](https://explorer.swellnetwork.io/address/0x6FB6C91e369fD151eB343de3BE76F3617FbFfDf2) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `83e2e2c4` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0x33274281…`](https://explorer.swellnetwork.io/address/0x3327428147E0cE4Cb185A82F756CaE0D429dbd2c) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `42c58b74` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0xaAe48810022E6aDd96a90c22e9aD26E51BA2E12b` | ✅ | ✅ | +| Token | `0xcd4c46724C19231f4F26e17bbe50866d236026c0` | ✅ | ✅ | +| Vault | `0xCcF00C2D8ED39ab8e128F2ad9fc6Ca23ecE8e50F` | ✅ | ✅ | +| Borrowing | `0xEFd941a28A3C553F96f6115Ca0499A30BcB0fe19` | ✅ | ✅ | +| Liquidation | `0x43CfB82df93a2dB299672254FB431DFA5F805EC9` | ✅ | ✅ | +| RiskManager | `0x90570126b8aDE769942361cB0c3A49574885F6cF` | ✅ | ✅ | +| BalanceForwarder | `0x71ca5e0CfCe7318978A516B89939D3D8898d159E` | ✅ | ✅ | +| Governance | `0x2DBd14Ffe7866F2BEeefdbb7295aa47BBbCf055C` | ✅ | ✅ | + +## EulerSwap V2 management implementation (unpacked from the implementation) + +EulerSwap delegatecalls management functions into a separate contract whose address is the public immutable `managementImpl`; it is verified from the same euler-swap pin. + +| Contract | Address | Bytecode | Embedded-immutable cross-check | +|----------|---------|----------|-------------------------------| +| EulerSwapManagement | `0x114E7907447c1E0bbB7afbA7dc6Fc904DAF70301` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (EUL): + +Carries the Paladin-audited source revision (natspec blob) — byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`773453b1`](https://github.com/euler-xyz/euler-earn/tree/773453b1f4a6f1d27a1cd0c6d8f6ada572503b23) (eulerEarnFactory): + +src/ identical to the baseline (empty diff). + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) (eulerSwapV1Factory, eulerSwapV1Implementation, eulerSwapV1Periphery): + +Tag eulerswap-1.0 (official V1 release), descendant of the baseline. src delta: SPDX headers UNLICENSED→GPL (14 files) + PR #99 event hoisting (new Events.sol; hook emits Swap with sender). No state-machine or math changes. foundry optimizer_runs raised 10000→1000000 post-audit, pre-deployment. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..ce71a2c 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..39fe65b 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..1befa2e 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {Owned} from "solmate/src/auth/Owned.sol"; +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (eulOFTAdapter): + +Adapter files blob-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) (evc): + +Descendant of the baseline and the last commit ever to touch src/ on origin/master — the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers — proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding). + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultImplementation + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`f52cb43b`](https://github.com/euler-xyz/euler-price-oracle/tree/f52cb43b587c7fa90a7e722d52698003451feb62)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (rEUL): + +Component files byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`eae25d38`](https://github.com/euler-xyz/evk-periphery/tree/eae25d382bb58aaaaa9f1a3a55567af993ce32be) (swapVerifier): + +> **This deployment predates the component baseline.** Its own audited anchor is [BailSec (`bailsec-evk-periphery-auxiliary-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/BailSec%20EVK%20Periphery%20Oracle%20Hook%20SwapVerifier.pdf): BailSec's March-2026 scope table pins SwapVerifier.sol at EXACTLY this commit (sole SwapVerifier finding: one acknowledged informational). The pin also contains the yaudit-swapverifier-update-2026 fix (b6046f44, cited verbatim in that report), so it is a doubly audit-pinned state. The pin→baseline delta is precisely the Enigma-Dark-reviewed refactor: TransferFromSender folded into the new MigrationHelper parent, with no logic change to the verify functions. +> +> The diff below therefore reads pin→baseline: it shows the audited changes this deployment predates, not unreviewed drift. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +new file mode 100644 +index 00000000..b70618d3 +--- /dev/null ++++ b/src/Swaps/MigrationHelper.sol +@@ -0,0 +1,153 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++pragma solidity ^0.8.0; ++ ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; ++import {SafeERC20Permit2Lib} from "euler-earn/libraries/SafeERC20Permit2Lib.sol"; ++import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; ++ ++/// @notice Minimal Aave V3 Pool interface used for position migrations. ++interface IAaveV3Pool { ++ function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) ++ external; ++} ++ ++/// @notice Minimal Morpho Blue interface used for position migrations. ++interface IMorpho { ++ struct MarketParams { ++ address loanToken; ++ address collateralToken; ++ address oracle; ++ address irm; ++ uint256 lltv; ++ } ++ ++ function borrow( ++ MarketParams calldata marketParams, ++ uint256 assets, ++ uint256 shares, ++ address onBehalf, ++ address receiver ++ ) external returns (uint256 assetsBorrowed, uint256 sharesBorrowed); ++ ++ function withdrawCollateral(MarketParams calldata marketParams, uint256 assets, address onBehalf, address receiver) ++ external; ++} ++ ++/// @title MigrationHelper ++/// @custom:security-contact security@euler.xyz ++/// @author Euler Labs (https://www.eulerlabs.com/) ++/// @notice Pulls tokens, and performs debt- and collateral-bearing actions on external lending protocols ++/// (Aave V3, Morpho Blue), on behalf of the EVC-authenticated sender. Used both as a gas-saving ++/// allowance sink for swaps and for migrating positions in and out of Euler. ++/// @dev This contract is trusted and can safely receive token allowances, Aave credit delegations and ++/// Morpho operator authorizations from users. Security model: every state-changing function pins the ++/// token source / protocol-side on-behalf account to the EVC-authenticated `_msgSender()`. A user ++/// grants this contract a standing allowance / credit delegation / operator authorization so a batch ++/// can act for them, but because the acting account is bound to that caller, the grant can only ever ++/// be exercised on the granting user's own position; a front-runner who replays the user's ++/// permit/delegation/authorization signature is authenticated as themselves and can only touch their ++/// own balance/position. `_msgSender()` resolves to the EVC on-behalf-of account, so an address the ++/// user has authorized as an EVC operator can likewise exercise these grants on the user's behalf — a ++/// consequence of the user's own operator authorization, consistent with the rest of the swap periphery. ++/// CAUTION: this means a *standing* Aave credit delegation or Morpho operator authorization left on this ++/// contract is exercisable by ANY EVC operator the user has authorized (for any unrelated reason): such an ++/// operator can borrow the user's delegated credit / withdraw their external collateral and direct the ++/// proceeds to themselves, bounded only by the external protocol's own health checks. The `_msgSender()` ++/// binding protects against third parties and replayers, not against the user's own operators. The Aave ++/// credit delegation / Morpho operator authorization should therefore be granted and revoked within the ++/// migration batch rather than left standing. The contract custodies no funds across calls, and safety ++/// does not depend on the `token`/`pool`/`morpho` arguments being canonical addresses. ++contract MigrationHelper is EVCUtil { ++ using SafeERC20 for IERC20; ++ ++ /// @notice Address of Permit2 contract ++ address public immutable permit2; ++ ++ /// @dev Aave V3 variable interest rate mode. Stable-rate borrowing is not supported. ++ uint256 internal constant AAVE_VARIABLE_RATE_MODE = 2; ++ ++ /// @notice Contract constructor ++ /// @param _evc Address of the EthereumVaultConnector contract ++ /// @param _permit2 Address of the Permit2 contract ++ constructor(address _evc, address _permit2) EVCUtil(_evc) { ++ permit2 = _permit2; ++ } ++ ++ /// @notice Pull tokens from sender to the designated receiver ++ /// @param token ERC20 token address ++ /// @param amount Amount of the token to transfer ++ /// @param to Receiver of the token ++ function transferFromSender(address token, uint256 amount, address to) public { ++ SafeERC20Permit2Lib.safeTransferFromWithPermit2(IERC20(token), _msgSender(), to, amount, permit2); ++ } ++ ++ /// @notice Pull the sender's entire live balance of a token, capped at `maxAmount`, and forward it to `to` ++ /// @param token The (possibly rebasing) ERC20 token to pull, e.g. an Aave aToken ++ /// @param maxAmount Upper bound on the amount to pull; the actual amount is min(balance, maxAmount) ++ /// @param to Recipient of the pulled tokens (e.g. the Swapper) ++ /// @return amount The amount actually transferred ++ /// @dev Reading the live balance avoids leaving dust behind when the token rebases (e.g. an Aave ++ /// aToken accruing interest between the user signing the permit and the batch executing), so the ++ /// whole position can be drained without an exact off-chain amount. ++ /// @dev `maxAmount` bounds the pull to the balance measured off-chain plus a small accrual buffer: an ++ /// unexpectedly large balance, or a larger pre-existing allowance, can never cause an over-pull. ++ /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. ++ /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying ++ /// the user's permit can only ever drain their own balance. ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) ++ external ++ returns (uint256 amount) ++ { ++ amount = IERC20(token).balanceOf(_msgSender()); ++ if (amount > maxAmount) amount = maxAmount; ++ // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. ++ if (amount == 0) return 0; ++ transferFromSender(token, amount, to); ++ } ++ ++ /// @notice Borrow an asset from Aave V3 on behalf of the sender and forward it to a receiver ++ /// @param pool Address of the Aave V3 Pool ++ /// @param asset The reserve asset to borrow ++ /// @param amount The amount of `asset` to borrow ++ /// @param to Recipient of the borrowed assets (e.g. the Swapper) ++ /// @dev The sender must have granted variable-debt credit delegation to this contract for `asset`. ++ /// @dev Aave sends the borrowed assets to msg.sender (this contract); only the amount actually ++ /// received from the borrow (the balance delta) is forwarded to `to`, so a non-canonical or ++ /// no-op `pool` cannot cause any pre-existing balance to be paid out, and no balance is left behind. ++ function aaveBorrowForSender(address pool, address asset, uint256 amount, address to) external { ++ uint256 balanceBefore = IERC20(asset).balanceOf(address(this)); ++ IAaveV3Pool(pool).borrow(asset, amount, AAVE_VARIABLE_RATE_MODE, 0, _msgSender()); ++ IERC20(asset).safeTransfer(to, IERC20(asset).balanceOf(address(this)) - balanceBefore); ++ } ++ ++ /// @notice Withdraw Morpho Blue collateral on behalf of the sender, directly to a receiver ++ /// @param morpho Address of the Morpho Blue contract ++ /// @param marketParams The Morpho market parameters identifying the position ++ /// @param amount The amount of collateral to withdraw ++ /// @param to Recipient of the withdrawn collateral (e.g. the Swapper) ++ /// @dev The sender must have authorized this contract as a Morpho operator. ++ function morphoWithdrawCollateralForSender( ++ address morpho, ++ IMorpho.MarketParams calldata marketParams, ++ uint256 amount, ++ address to ++ ) external { ++ IMorpho(morpho).withdrawCollateral(marketParams, amount, _msgSender(), to); ++ } ++ ++ /// @notice Borrow from a Morpho Blue market on behalf of the sender, directly to a receiver ++ /// @param morpho Address of the Morpho Blue contract ++ /// @param marketParams The Morpho market parameters identifying the market ++ /// @param amount The amount of loan asset to borrow ++ /// @param to Recipient of the borrowed assets (e.g. the Swapper) ++ /// @dev The sender must have authorized this contract as a Morpho operator. ++ function morphoBorrowForSender( ++ address morpho, ++ IMorpho.MarketParams calldata marketParams, ++ uint256 amount, ++ address to ++ ) external { ++ IMorpho(morpho).borrow(marketParams, amount, 0, _msgSender(), to); ++ } ++} +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index a05a0d84..23a3c2fd 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -3,16 +3,17 @@ + pragma solidity ^0.8.0; + + import {IEVault} from "evk/EVault/IEVault.sol"; +-import {TransferFromSender} from "./TransferFromSender.sol"; ++import {MigrationHelper} from "./MigrationHelper.sol"; + import {IEVault, IERC4626} from "evk/EVault/IEVault.sol"; + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SwapVerifier + /// @custom:security-contact security@euler.xyz + /// @author Euler Labs (https://www.eulerlabs.com/) +-/// @notice Simple contract used to verify post swap conditions. Includes TransferFromSender helper for gas savings. ++/// @notice Simple contract used to verify post swap conditions. Inherits the MigrationHelper from-sender ++/// helpers (transferFromSender and position migration primitives) for gas savings. + /// @dev This contract is the only trusted code in the EVK swap periphery +-contract SwapVerifier is TransferFromSender { ++contract SwapVerifier is MigrationHelper { + error SwapVerifier_skimMin(); + error SwapVerifier_depositMin(); + error SwapVerifier_transferMin(); +@@ -22,7 +23,7 @@ contract SwapVerifier is TransferFromSender { + /// @notice Contract constructor + /// @param evc Address of the EthereumVaultConnector contract + /// @param permit2 Address of the Permit2 contract +- constructor(address evc, address permit2) TransferFromSender(evc, permit2) {} ++ constructor(address evc, address permit2) MigrationHelper(evc, permit2) {} + + /// @notice Verify results of a regular swap, when bought tokens are sent to the vault and skim for the buyer + /// @param vault The EVault to query +diff --git a/src/Swaps/TransferFromSender.sol b/src/Swaps/TransferFromSender.sol +deleted file mode 100644 +index 01ab58ef..00000000 +--- a/src/Swaps/TransferFromSender.sol ++++ /dev/null +@@ -1,30 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +- +-pragma solidity ^0.8.0; +- +-import {SafeERC20Permit2Lib, IERC20} from "euler-earn/libraries/SafeERC20Permit2Lib.sol"; +-import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +- +-/// @title TransferFromSender +-/// @custom:security-contact security@euler.xyz +-/// @author Euler Labs (https://www.eulerlabs.com/) +-/// @notice Simple contract used to pull tokens from the sender. +-/// @dev This contract is trusted and can safely receive allowance on token transfers from users. +-contract TransferFromSender is EVCUtil { +- /// @notice Address of Permit2 contract +- address public immutable permit2; +- +- /// @notice Contract constructor +- /// @param _permit2 Address of the Permit2 contract +- constructor(address _evc, address _permit2) EVCUtil(_evc) { +- permit2 = _permit2; +- } +- +- /// @notice Pull tokens from sender to the designated receiver +- /// @param token ERC20 token address +- /// @param amount Amount of the token to transfer +- /// @param to Receiver of the token +- function transferFromSender(address token, uint256 amount, address to) public { +- SafeERC20Permit2Lib.safeTransferFromWithPermit2(IERC20(token), _msgSender(), to, amount, permit2); +- } +-} +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/239.md b/verify/239.md new file mode 100644 index 0000000..675b628 --- /dev/null +++ b/verify/239.md @@ -0,0 +1,1060 @@ +# TAC — Deployed Code Verification + +Chain ID: 239 · Bytecode-proven: **21/21** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0x45ff89cD…`](https://explorer.tac.build/address/0x45ff89cD0e976392703048F4A4314A2010ee64b8) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `47294620` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0x38C04385…`](https://explorer.tac.build/address/0x38C043856A109066d64a60c82e07848a1C58e7Dc) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `0b021e3f` | ≡ baseline | — | +| eulOFTAdapter | [`0xe7c41548…`](https://explorer.tac.build/address/0xe7c415484348d14c0e6B8C18E110D72EcA17d306) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `1036d1c0` | ≡ baseline | — | +| eVaultFactory | [`0x2b21621b…`](https://explorer.tac.build/address/0x2b21621b8Ef1406699a99071ce04ec14cCd50677) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0x1974899F…`](https://explorer.tac.build/address/0x1974899F5d6B5a1f8E63b2e8Ad60e14BAC3E7980) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `8c001272` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0x01F594c6…`](https://explorer.tac.build/address/0x01F594c66A5561b90Bc782dD0297f294cD668b64) | [`ethereum-vault-connector@a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) | ✅ `b12f6d72` | +58/−11 vs baseline | EVCUtil helper + signer-exclusion hardening | +| oracleRouterFactory | [`0x0512F7cb…`](https://explorer.tac.build/address/0x0512F7cbc4Fd9d8BC47FfFa3aA0372bA2375158E) | [`evk-periphery@96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0x4C3D26D7…`](https://explorer.tac.build/address/0x4C3D26D7Eb6D5AA62CFD99624ad4Ff3351E4B129) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0xCf623E50…`](https://explorer.tac.build/address/0xCf623E50430CCb55214985F9C986a5Fa50aD7686) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0xF7a9F90b…`](https://explorer.tac.build/address/0xF7a9F90b5ACb4EE4Cd536940142A04522D28e0Aa) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0x6D83f642…`](https://explorer.tac.build/address/0x6D83f642A1F0206b08f4F035197F9Eee553AbFC9) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `2fc2cdd1` | +3/−5 vs baseline | formatting only | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0x7670572a…`](https://explorer.tac.build/address/0x7670572aa76E6140400A948e7AAFAB0210a86d9f) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `c9ee150e` | +18/−18 vs baseline | import-path style only | +| eulerEarnPublicAllocator | [`0x4873ff8a…`](https://explorer.tac.build/address/0x4873ff8a70aA92443321Edb34a48f6aBfA7feB96) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV1Factory | [`0x6A721609…`](https://explorer.tac.build/address/0x6A72160963a562f21387B166aF31a92D154106fb) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `7c9a247e` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Implementation | [`0xDFfaC13f…`](https://explorer.tac.build/address/0xDFfaC13fC142Fc1d8E55226dB9c98f4b66371a3c) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `20cae9a4` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Periphery | [`0xAF596563…`](https://explorer.tac.build/address/0xAF596563109C753b9c5e73DD596DD4bB247964cA) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `703cfc72` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV2Factory | [`0xb0b53c1A…`](https://explorer.tac.build/address/0xb0b53c1A8046D92027B69D9f6D9C7cFC0f363933) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `4bdd5d47` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0x32Da74f7…`](https://explorer.tac.build/address/0x32Da74f7bC1988c1c39adB561b6e9D2a6F33D404) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `408124d9` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0xD356C065…`](https://explorer.tac.build/address/0xD356C065777871B37Cb0D3C7761b8820c832BC57) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `f98bd760` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0xb7F14f64…`](https://explorer.tac.build/address/0xb7F14f649770fB7784A02A94946D14E80f79d660) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `83e2e2c4` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0xd3ee9112…`](https://explorer.tac.build/address/0xd3ee91128294Ca8231260891BEC6Da7d258De7B6) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `42c58b74` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0x4f345Ac5a7981020b602922Ce791C9F45b6D93Db` | ✅ | ✅ | +| Token | `0xce17b9b320f5fdda38D6d51A55DdCBca243FBa0d` | ✅ | ✅ | +| Vault | `0xAd39579e31eB97D757ae2670a86Ca774C1d31551` | ✅ | ✅ | +| Borrowing | `0x6bD5D4b4e90bb1a8735b21722365244e40fc6293` | ✅ | ✅ | +| Liquidation | `0xDde44a41c56bE95EfB61e4a9394f9B2Ef76Ee8A3` | ✅ | ✅ | +| RiskManager | `0x418687de483870905B43e3c9ce129980A031ebA1` | ✅ | ✅ | +| BalanceForwarder | `0x7e58Fe64A5875a0B8E1A721CCEb940762CB5d0Ab` | ✅ | ✅ | +| Governance | `0x1aD8dCc27F06794F2EbaaFBa50e21FEdCf931C88` | ✅ | ✅ | + +## EulerSwap V2 management implementation (unpacked from the implementation) + +EulerSwap delegatecalls management functions into a separate contract whose address is the public immutable `managementImpl`; it is verified from the same euler-swap pin. + +| Contract | Address | Bytecode | Embedded-immutable cross-check | +|----------|---------|----------|-------------------------------| +| EulerSwapManagement | `0x6bb717C08E0CF7fcC59CD695B4FDee38eD9B9d69` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (EUL): + +Carries the Paladin-audited source revision (natspec blob) — byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnFactory, eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) (eulerSwapV1Factory, eulerSwapV1Implementation, eulerSwapV1Periphery): + +Tag eulerswap-1.0 (official V1 release), descendant of the baseline. src delta: SPDX headers UNLICENSED→GPL (14 files) + PR #99 event hoisting (new Events.sol; hook emits Swap with sender). No state-machine or math changes. foundry optimizer_runs raised 10000→1000000 post-audit, pre-deployment. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..ce71a2c 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..39fe65b 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..1befa2e 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {Owned} from "solmate/src/auth/Owned.sol"; +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (eulOFTAdapter): + +Adapter files blob-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) (evc): + +Descendant of the baseline and the last commit ever to touch src/ on origin/master — the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers — proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding). + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultImplementation + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`f52cb43b`](https://github.com/euler-xyz/euler-price-oracle/tree/f52cb43b587c7fa90a7e722d52698003451feb62)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (rEUL): + +Component files byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (swapVerifier): + +Descendant of the baseline by 3 days (the merge adding the Enigma report PDF). src/Swaps delta is 100% non-semantic forge-fmt re-wrapping. This IS the Enigma-fixes-included state as deployed on 13 chains. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +index b70618d3..d210ab47 100644 +--- a/src/Swaps/MigrationHelper.sol ++++ b/src/Swaps/MigrationHelper.sol +@@ -95,10 +95,7 @@ contract MigrationHelper is EVCUtil { + /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. + /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying + /// the user's permit can only ever drain their own balance. +- function transferBalanceFromSender(address token, uint256 maxAmount, address to) +- external +- returns (uint256 amount) +- { ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) external returns (uint256 amount) { + amount = IERC20(token).balanceOf(_msgSender()); + if (amount > maxAmount) amount = maxAmount; + // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index 23a3c2fd..ec881e76 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -69,7 +69,8 @@ contract SwapVerifier is MigrationHelper { + /// @param receiver The address to transfer the asset to + /// @param amountMin The minimum amount of the asset that must be available before transfer + /// @param deadline A timestamp after which the transfer will revert +- /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if the minimum is met ++ /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if ++ /// the minimum is met + function verifyAmountMinAndTransfer(address asset, address receiver, uint256 amountMin, uint256 deadline) external { + if (deadline < block.timestamp) revert SwapVerifier_pastDeadline(); +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/2818.md b/verify/2818.md new file mode 100644 index 0000000..8fc17bf --- /dev/null +++ b/verify/2818.md @@ -0,0 +1,1173 @@ +# Morph — Deployed Code Verification + +Chain ID: 2818 · Bytecode-proven: **18/18** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0x7bF00B86…`](https://explorer.morph.network/address/0x7bF00B8638d0eBE917C82B286Fc07E86988F3A1C) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `47294620` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0x5E2901d2…`](https://explorer.morph.network/address/0x5E2901d24fc83eCE7589e7A7d3b1e6D80739789d) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `0b021e3f` | ≡ baseline | — | +| eulOFTAdapter | [`0x9895149F…`](https://explorer.morph.network/address/0x9895149F3324666d94664C159Af0cd026eb53761) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `1036d1c0` | ≡ baseline | — | +| eVaultFactory | [`0x1a1bdF62…`](https://explorer.morph.network/address/0x1a1bdF62Fe7170c652f03fF153977C26fBe7b2E1) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0xC98f21E7…`](https://explorer.morph.network/address/0xC98f21E7b1F12ab225386226D022a67E65D8B0cE) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `8c001272` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0xC7c31B1E…`](https://explorer.morph.network/address/0xC7c31B1E7Cac36478C62f876F357b95d9cAd9817) | [`ethereum-vault-connector@7b2f05f8`](https://github.com/euler-xyz/ethereum-vault-connector/tree/7b2f05f8f2fc093f679463209dea202e9af3b120) | ✅ `58879eba` | +59/−11 vs baseline | Morph deployment-branch additions | +| oracleRouterFactory | [`0x1e809496…`](https://explorer.morph.network/address/0x1e80949625ab6b09a5749f00a63d48887ba3B696) | [`evk-periphery@96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0x235597e3…`](https://explorer.morph.network/address/0x235597e32131A6681592Ac276c967a5b8c89dCb3) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0xA394128F…`](https://explorer.morph.network/address/0xA394128F6b04A0AbcA7feaa12145Da9Aa6B24686) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0x433438DD…`](https://explorer.morph.network/address/0x433438DD80353fB1893253348b7b14f821b4cCFB) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0xD38D4F98…`](https://explorer.morph.network/address/0xD38D4F982Ca00365e349dC128C833289be4774c9) | [`evk-periphery@eae25d38`](https://github.com/euler-xyz/evk-periphery/tree/eae25d382bb58aaaaa9f1a3a55567af993ce32be) | ✅ `9469decd` | predates (+158/−34 audited later) | pre-refactor state (audit-pinned) | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0x4A6727aA…`](https://explorer.morph.network/address/0x4A6727aA2d1979C0366751c7a81615500f0186E4) | [`euler-earn@bece7172`](https://github.com/euler-xyz/euler-earn/tree/bece7172a87551e6943a52b08c9a0117eb02c6c3) | ✅ `c65c6dcf` | +18/−18 vs baseline | import-path style only | +| eulerEarnPublicAllocator | [`0x776043C5…`](https://explorer.morph.network/address/0x776043C581c7b30164b92358be317b16489C510b) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV2Factory | [`0x59652301…`](https://explorer.morph.network/address/0x5965230117acd46E88CA13e7D44E33cD166c1E44) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `4bdd5d47` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0xDA4d6a51…`](https://explorer.morph.network/address/0xDA4d6a51cdF37d93C84071192611B0544B4454d8) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `408124d9` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0x9C0689e0…`](https://explorer.morph.network/address/0x9C0689e034D5bfDCc190F062b70c364c4764EF35) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `f98bd760` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0x2348C396…`](https://explorer.morph.network/address/0x2348C3967F61b235501Ea74eE8e95F84D752dDeA) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `83e2e2c4` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0xce4Ef4F4…`](https://explorer.morph.network/address/0xce4Ef4F4c590FE00c213e1A458743d12e7301268) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `42c58b74` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0xFEfF486FB1b132e6CaeC3318916358E405Cfeb7c` | ✅ | ✅ | +| Token | `0x2ef8c5df7919AEc5C6495DADD63b6246345dfe94` | ✅ | ✅ | +| Vault | `0x88C78B173123fb7695119f69CA28BE240D11Cf71` | ✅ | ✅ | +| Borrowing | `0x91f9f7d2f1082c7D1D64D02a34b71BC4d2e8D0Fc` | ✅ | ✅ | +| Liquidation | `0xd7D92E8e18123D572a12168EbFAD581e8A7F53D7` | ✅ | ✅ | +| RiskManager | `0xc1Daba4109b0096F58c7d70e2D5D224577a4396E` | ✅ | ✅ | +| BalanceForwarder | `0x851e7baea325F78e67AAD565009dF684f71ad2E3` | ✅ | ✅ | +| Governance | `0x16E2f5319B8e878577AcA9a893592d7E4443bB15` | ✅ | ✅ | + +## EulerSwap V2 management implementation (unpacked from the implementation) + +EulerSwap delegatecalls management functions into a separate contract whose address is the public immutable `managementImpl`; it is verified from the same euler-swap pin. + +| Contract | Address | Bytecode | Embedded-immutable cross-check | +|----------|---------|----------|-------------------------------| +| EulerSwapManagement | `0x90841B9092F94510db692F17F9AF3105061f029E` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (EUL): + +Carries the Paladin-audited source revision (natspec blob) — byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`bece7172`](https://github.com/euler-xyz/euler-earn/tree/bece7172a87551e6943a52b08c9a0117eb02c6c3) (eulerEarnFactory): + +Monad/Morph deployments: public euler-earn master commit (“fix: absolute import paths”, 2025-10-14); descendant of the baseline with import-path-style deltas only. Compiled at the repo profile (0.8.26, runs 200, via_ir) with the deploy workspace’s OpenZeppelin v5.1.0. + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (eulOFTAdapter): + +Adapter files blob-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`7b2f05f8`](https://github.com/euler-xyz/ethereum-vault-connector/tree/7b2f05f8f2fc093f679463209dea202e9af3b120) (evc): + +Morph deployment: tip of the public origin/deployment-morph branch (“facilitate Morph deployment”, 2025-02-13); descendant of the baseline, compiled at 0.8.24/runs 20000/cancun. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..df0e204 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,9 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; ++ address internal constant MORPH_PREDEPLOYS = 0x5300000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1048,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS) && !haveCommonOwnerInternal(signer, MORPH_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultImplementation + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`f52cb43b`](https://github.com/euler-xyz/euler-price-oracle/tree/f52cb43b587c7fa90a7e722d52698003451feb62)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (rEUL): + +Component files byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`eae25d38`](https://github.com/euler-xyz/evk-periphery/tree/eae25d382bb58aaaaa9f1a3a55567af993ce32be) (swapVerifier): + +> **This deployment predates the component baseline.** Its own audited anchor is [BailSec (`bailsec-evk-periphery-auxiliary-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/BailSec%20EVK%20Periphery%20Oracle%20Hook%20SwapVerifier.pdf): BailSec's March-2026 scope table pins SwapVerifier.sol at EXACTLY this commit (sole SwapVerifier finding: one acknowledged informational). The pin also contains the yaudit-swapverifier-update-2026 fix (b6046f44, cited verbatim in that report), so it is a doubly audit-pinned state. The pin→baseline delta is precisely the Enigma-Dark-reviewed refactor: TransferFromSender folded into the new MigrationHelper parent, with no logic change to the verify functions. +> +> The diff below therefore reads pin→baseline: it shows the audited changes this deployment predates, not unreviewed drift. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +new file mode 100644 +index 00000000..b70618d3 +--- /dev/null ++++ b/src/Swaps/MigrationHelper.sol +@@ -0,0 +1,153 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++pragma solidity ^0.8.0; ++ ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; ++import {SafeERC20Permit2Lib} from "euler-earn/libraries/SafeERC20Permit2Lib.sol"; ++import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; ++ ++/// @notice Minimal Aave V3 Pool interface used for position migrations. ++interface IAaveV3Pool { ++ function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) ++ external; ++} ++ ++/// @notice Minimal Morpho Blue interface used for position migrations. ++interface IMorpho { ++ struct MarketParams { ++ address loanToken; ++ address collateralToken; ++ address oracle; ++ address irm; ++ uint256 lltv; ++ } ++ ++ function borrow( ++ MarketParams calldata marketParams, ++ uint256 assets, ++ uint256 shares, ++ address onBehalf, ++ address receiver ++ ) external returns (uint256 assetsBorrowed, uint256 sharesBorrowed); ++ ++ function withdrawCollateral(MarketParams calldata marketParams, uint256 assets, address onBehalf, address receiver) ++ external; ++} ++ ++/// @title MigrationHelper ++/// @custom:security-contact security@euler.xyz ++/// @author Euler Labs (https://www.eulerlabs.com/) ++/// @notice Pulls tokens, and performs debt- and collateral-bearing actions on external lending protocols ++/// (Aave V3, Morpho Blue), on behalf of the EVC-authenticated sender. Used both as a gas-saving ++/// allowance sink for swaps and for migrating positions in and out of Euler. ++/// @dev This contract is trusted and can safely receive token allowances, Aave credit delegations and ++/// Morpho operator authorizations from users. Security model: every state-changing function pins the ++/// token source / protocol-side on-behalf account to the EVC-authenticated `_msgSender()`. A user ++/// grants this contract a standing allowance / credit delegation / operator authorization so a batch ++/// can act for them, but because the acting account is bound to that caller, the grant can only ever ++/// be exercised on the granting user's own position; a front-runner who replays the user's ++/// permit/delegation/authorization signature is authenticated as themselves and can only touch their ++/// own balance/position. `_msgSender()` resolves to the EVC on-behalf-of account, so an address the ++/// user has authorized as an EVC operator can likewise exercise these grants on the user's behalf — a ++/// consequence of the user's own operator authorization, consistent with the rest of the swap periphery. ++/// CAUTION: this means a *standing* Aave credit delegation or Morpho operator authorization left on this ++/// contract is exercisable by ANY EVC operator the user has authorized (for any unrelated reason): such an ++/// operator can borrow the user's delegated credit / withdraw their external collateral and direct the ++/// proceeds to themselves, bounded only by the external protocol's own health checks. The `_msgSender()` ++/// binding protects against third parties and replayers, not against the user's own operators. The Aave ++/// credit delegation / Morpho operator authorization should therefore be granted and revoked within the ++/// migration batch rather than left standing. The contract custodies no funds across calls, and safety ++/// does not depend on the `token`/`pool`/`morpho` arguments being canonical addresses. ++contract MigrationHelper is EVCUtil { ++ using SafeERC20 for IERC20; ++ ++ /// @notice Address of Permit2 contract ++ address public immutable permit2; ++ ++ /// @dev Aave V3 variable interest rate mode. Stable-rate borrowing is not supported. ++ uint256 internal constant AAVE_VARIABLE_RATE_MODE = 2; ++ ++ /// @notice Contract constructor ++ /// @param _evc Address of the EthereumVaultConnector contract ++ /// @param _permit2 Address of the Permit2 contract ++ constructor(address _evc, address _permit2) EVCUtil(_evc) { ++ permit2 = _permit2; ++ } ++ ++ /// @notice Pull tokens from sender to the designated receiver ++ /// @param token ERC20 token address ++ /// @param amount Amount of the token to transfer ++ /// @param to Receiver of the token ++ function transferFromSender(address token, uint256 amount, address to) public { ++ SafeERC20Permit2Lib.safeTransferFromWithPermit2(IERC20(token), _msgSender(), to, amount, permit2); ++ } ++ ++ /// @notice Pull the sender's entire live balance of a token, capped at `maxAmount`, and forward it to `to` ++ /// @param token The (possibly rebasing) ERC20 token to pull, e.g. an Aave aToken ++ /// @param maxAmount Upper bound on the amount to pull; the actual amount is min(balance, maxAmount) ++ /// @param to Recipient of the pulled tokens (e.g. the Swapper) ++ /// @return amount The amount actually transferred ++ /// @dev Reading the live balance avoids leaving dust behind when the token rebases (e.g. an Aave ++ /// aToken accruing interest between the user signing the permit and the batch executing), so the ++ /// whole position can be drained without an exact off-chain amount. ++ /// @dev `maxAmount` bounds the pull to the balance measured off-chain plus a small accrual buffer: an ++ /// unexpectedly large balance, or a larger pre-existing allowance, can never cause an over-pull. ++ /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. ++ /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying ++ /// the user's permit can only ever drain their own balance. ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) ++ external ++ returns (uint256 amount) ++ { ++ amount = IERC20(token).balanceOf(_msgSender()); ++ if (amount > maxAmount) amount = maxAmount; ++ // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. ++ if (amount == 0) return 0; ++ transferFromSender(token, amount, to); ++ } ++ ++ /// @notice Borrow an asset from Aave V3 on behalf of the sender and forward it to a receiver ++ /// @param pool Address of the Aave V3 Pool ++ /// @param asset The reserve asset to borrow ++ /// @param amount The amount of `asset` to borrow ++ /// @param to Recipient of the borrowed assets (e.g. the Swapper) ++ /// @dev The sender must have granted variable-debt credit delegation to this contract for `asset`. ++ /// @dev Aave sends the borrowed assets to msg.sender (this contract); only the amount actually ++ /// received from the borrow (the balance delta) is forwarded to `to`, so a non-canonical or ++ /// no-op `pool` cannot cause any pre-existing balance to be paid out, and no balance is left behind. ++ function aaveBorrowForSender(address pool, address asset, uint256 amount, address to) external { ++ uint256 balanceBefore = IERC20(asset).balanceOf(address(this)); ++ IAaveV3Pool(pool).borrow(asset, amount, AAVE_VARIABLE_RATE_MODE, 0, _msgSender()); ++ IERC20(asset).safeTransfer(to, IERC20(asset).balanceOf(address(this)) - balanceBefore); ++ } ++ ++ /// @notice Withdraw Morpho Blue collateral on behalf of the sender, directly to a receiver ++ /// @param morpho Address of the Morpho Blue contract ++ /// @param marketParams The Morpho market parameters identifying the position ++ /// @param amount The amount of collateral to withdraw ++ /// @param to Recipient of the withdrawn collateral (e.g. the Swapper) ++ /// @dev The sender must have authorized this contract as a Morpho operator. ++ function morphoWithdrawCollateralForSender( ++ address morpho, ++ IMorpho.MarketParams calldata marketParams, ++ uint256 amount, ++ address to ++ ) external { ++ IMorpho(morpho).withdrawCollateral(marketParams, amount, _msgSender(), to); ++ } ++ ++ /// @notice Borrow from a Morpho Blue market on behalf of the sender, directly to a receiver ++ /// @param morpho Address of the Morpho Blue contract ++ /// @param marketParams The Morpho market parameters identifying the market ++ /// @param amount The amount of loan asset to borrow ++ /// @param to Recipient of the borrowed assets (e.g. the Swapper) ++ /// @dev The sender must have authorized this contract as a Morpho operator. ++ function morphoBorrowForSender( ++ address morpho, ++ IMorpho.MarketParams calldata marketParams, ++ uint256 amount, ++ address to ++ ) external { ++ IMorpho(morpho).borrow(marketParams, amount, 0, _msgSender(), to); ++ } ++} +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index a05a0d84..23a3c2fd 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -3,16 +3,17 @@ + pragma solidity ^0.8.0; + + import {IEVault} from "evk/EVault/IEVault.sol"; +-import {TransferFromSender} from "./TransferFromSender.sol"; ++import {MigrationHelper} from "./MigrationHelper.sol"; + import {IEVault, IERC4626} from "evk/EVault/IEVault.sol"; + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SwapVerifier + /// @custom:security-contact security@euler.xyz + /// @author Euler Labs (https://www.eulerlabs.com/) +-/// @notice Simple contract used to verify post swap conditions. Includes TransferFromSender helper for gas savings. ++/// @notice Simple contract used to verify post swap conditions. Inherits the MigrationHelper from-sender ++/// helpers (transferFromSender and position migration primitives) for gas savings. + /// @dev This contract is the only trusted code in the EVK swap periphery +-contract SwapVerifier is TransferFromSender { ++contract SwapVerifier is MigrationHelper { + error SwapVerifier_skimMin(); + error SwapVerifier_depositMin(); + error SwapVerifier_transferMin(); +@@ -22,7 +23,7 @@ contract SwapVerifier is TransferFromSender { + /// @notice Contract constructor + /// @param evc Address of the EthereumVaultConnector contract + /// @param permit2 Address of the Permit2 contract +- constructor(address evc, address permit2) TransferFromSender(evc, permit2) {} ++ constructor(address evc, address permit2) MigrationHelper(evc, permit2) {} + + /// @notice Verify results of a regular swap, when bought tokens are sent to the vault and skim for the buyer + /// @param vault The EVault to query +diff --git a/src/Swaps/TransferFromSender.sol b/src/Swaps/TransferFromSender.sol +deleted file mode 100644 +index 01ab58ef..00000000 +--- a/src/Swaps/TransferFromSender.sol ++++ /dev/null +@@ -1,30 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +- +-pragma solidity ^0.8.0; +- +-import {SafeERC20Permit2Lib, IERC20} from "euler-earn/libraries/SafeERC20Permit2Lib.sol"; +-import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +- +-/// @title TransferFromSender +-/// @custom:security-contact security@euler.xyz +-/// @author Euler Labs (https://www.eulerlabs.com/) +-/// @notice Simple contract used to pull tokens from the sender. +-/// @dev This contract is trusted and can safely receive allowance on token transfers from users. +-contract TransferFromSender is EVCUtil { +- /// @notice Address of Permit2 contract +- address public immutable permit2; +- +- /// @notice Contract constructor +- /// @param _permit2 Address of the Permit2 contract +- constructor(address _evc, address _permit2) EVCUtil(_evc) { +- permit2 = _permit2; +- } +- +- /// @notice Pull tokens from sender to the designated receiver +- /// @param token ERC20 token address +- /// @param amount Amount of the token to transfer +- /// @param to Receiver of the token +- function transferFromSender(address token, uint256 amount, address to) public { +- SafeERC20Permit2Lib.safeTransferFromWithPermit2(IERC20(token), _msgSender(), to, amount, permit2); +- } +-} +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/42161.md b/verify/42161.md new file mode 100644 index 0000000..4e40663 --- /dev/null +++ b/verify/42161.md @@ -0,0 +1,1060 @@ +# Arbitrum — Deployed Code Verification + +Chain ID: 42161 · Bytecode-proven: **21/21** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0xbCD29c1B…`](https://arbiscan.io/address/0xbCD29c1B596d9fFAfaa6F90780956b4D3d47832f) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `47294620` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0x462cD9E0…`](https://arbiscan.io/address/0x462cD9E0247b2e63831c3189aE738E5E9a5a4b64) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `0b021e3f` | ≡ baseline | — | +| eulOFTAdapter | [`0x174834a9…`](https://arbiscan.io/address/0x174834a9DE4C2f0c13c7353e62C229E8D607c808) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `1036d1c0` | ≡ baseline | — | +| eVaultFactory | [`0x78Df1CF5…`](https://arbiscan.io/address/0x78Df1CF5bf06a7f27f2ACc580B934238C1b80D50) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0x832fF401…`](https://arbiscan.io/address/0x832fF4011A3164ea76ceA06A313EE0B6CD72ba96) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `8c001272` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0x6302ef0F…`](https://arbiscan.io/address/0x6302ef0F34100CDDFb5489fbcB6eE1AA95CD1066) | [`ethereum-vault-connector@a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) | ✅ `b12f6d72` | +58/−11 vs baseline | EVCUtil helper + signer-exclusion hardening | +| oracleRouterFactory | [`0x22d51Db4…`](https://arbiscan.io/address/0x22d51Db42A59862D4F8c135C4406AEf9854ABFF3) | [`evk-periphery@96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0x06c1Ab0A…`](https://arbiscan.io/address/0x06c1Ab0A1672E8FC7F7D10BD7B869B4116D18a2c) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0xFA31599a…`](https://arbiscan.io/address/0xFA31599a4928c2d57C0dd77DFCA5DA1E94E6D2D2) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0x924C73ab…`](https://arbiscan.io/address/0x924C73abAa350800fc22c11ffdFB09641106E3ce) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0xdABeBFF7…`](https://arbiscan.io/address/0xdABeBFF75f047E725D9aC978770107491C100bbB) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `2fc2cdd1` | +3/−5 vs baseline | formatting only | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0xB9B5d62B…`](https://arbiscan.io/address/0xB9B5d62B9fE9E1B505466e75817aB178A1D2ec9d) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `c9ee150e` | +18/−18 vs baseline | import-path style only | +| eulerEarnPublicAllocator | [`0x0161FE2C…`](https://arbiscan.io/address/0x0161FE2CA6ED39b5D0811a94b87AC628677Ae020) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV1Factory | [`0x7949bE8B…`](https://arbiscan.io/address/0x7949bE8B154D7B5ce6E75cBfc646AeF3a25970E2) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `7c9a247e` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Implementation | [`0x04671F89…`](https://arbiscan.io/address/0x04671F895c7d9EAbF33FF1dfF41269E6Fea835D1) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `20cae9a4` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Periphery | [`0x804485f5…`](https://arbiscan.io/address/0x804485f5B6c293f8d63f697E9662CD4a8765858A) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `703cfc72` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV2Factory | [`0x138AB9B3…`](https://arbiscan.io/address/0x138AB9B33741B25bb7BcDa466175c8B2E2b96dc4) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `4bdd5d47` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0xAF6412D5…`](https://arbiscan.io/address/0xAF6412D58024874b0Ffc4138FfF95fc73b372977) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `408124d9` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0x223c1a20…`](https://arbiscan.io/address/0x223c1a20A6992a0F1E7066eD924619c3156DDA15) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `f98bd760` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0xA6fCC47f…`](https://arbiscan.io/address/0xA6fCC47f8D930f096F8749C7C7D335871bc71C0D) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `83e2e2c4` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0x99C341F0…`](https://arbiscan.io/address/0x99C341F07098ba70aC1130c479103Dc2366dbBD7) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `42c58b74` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0xD84Bb26b197fa11C2538Ba69eB39390c2F5a31e0` | ✅ | ✅ | +| Token | `0xbEC1FA1CEc857607a1734a31d7e13248cc35365b` | ✅ | ✅ | +| Vault | `0x9203c109F1731e3e5d0962C5E8db57e2f96711c2` | ✅ | ✅ | +| Borrowing | `0x8575750CE6A4A97d7d51E3bFf9BDC1bEc317E24e` | ✅ | ✅ | +| Liquidation | `0xb36dc8B7DDA8E5eaD9F0F2e7700BAB65d3105d42` | ✅ | ✅ | +| RiskManager | `0xe7426Ca08e870e6fb8b03491B2d6689441867E9F` | ✅ | ✅ | +| BalanceForwarder | `0x2cd7E23C2b67BEC9c4ae781E20f7c06b76E422B8` | ✅ | ✅ | +| Governance | `0x324996a18a07E6d41e6a36991C0C86E81241d9AF` | ✅ | ✅ | + +## EulerSwap V2 management implementation (unpacked from the implementation) + +EulerSwap delegatecalls management functions into a separate contract whose address is the public immutable `managementImpl`; it is verified from the same euler-swap pin. + +| Contract | Address | Bytecode | Embedded-immutable cross-check | +|----------|---------|----------|-------------------------------| +| EulerSwapManagement | `0xE3f7BdE71c02708fC1e7feAfe2AF442dF84731F1` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (EUL): + +Carries the Paladin-audited source revision (natspec blob) — byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnFactory, eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) (eulerSwapV1Factory, eulerSwapV1Implementation, eulerSwapV1Periphery): + +Tag eulerswap-1.0 (official V1 release), descendant of the baseline. src delta: SPDX headers UNLICENSED→GPL (14 files) + PR #99 event hoisting (new Events.sol; hook emits Swap with sender). No state-machine or math changes. foundry optimizer_runs raised 10000→1000000 post-audit, pre-deployment. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..ce71a2c 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..39fe65b 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..1befa2e 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {Owned} from "solmate/src/auth/Owned.sol"; +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (eulOFTAdapter): + +Adapter files blob-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) (evc): + +Descendant of the baseline and the last commit ever to touch src/ on origin/master — the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers — proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding). + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultImplementation + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`f52cb43b`](https://github.com/euler-xyz/euler-price-oracle/tree/f52cb43b587c7fa90a7e722d52698003451feb62)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (rEUL): + +Component files byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (swapVerifier): + +Descendant of the baseline by 3 days (the merge adding the Enigma report PDF). src/Swaps delta is 100% non-semantic forge-fmt re-wrapping. This IS the Enigma-fixes-included state as deployed on 13 chains. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +index b70618d3..d210ab47 100644 +--- a/src/Swaps/MigrationHelper.sol ++++ b/src/Swaps/MigrationHelper.sol +@@ -95,10 +95,7 @@ contract MigrationHelper is EVCUtil { + /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. + /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying + /// the user's permit can only ever drain their own balance. +- function transferBalanceFromSender(address token, uint256 maxAmount, address to) +- external +- returns (uint256 amount) +- { ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) external returns (uint256 amount) { + amount = IERC20(token).balanceOf(_msgSender()); + if (amount > maxAmount) amount = maxAmount; + // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index 23a3c2fd..ec881e76 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -69,7 +69,8 @@ contract SwapVerifier is MigrationHelper { + /// @param receiver The address to transfer the asset to + /// @param amountMin The minimum amount of the asset that must be available before transfer + /// @param deadline A timestamp after which the transfer will revert +- /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if the minimum is met ++ /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if ++ /// the minimum is met + function verifyAmountMinAndTransfer(address asset, address receiver, uint256 amountMin, uint256 deadline) external { + if (deadline < block.timestamp) revert SwapVerifier_pastDeadline(); +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/43114.md b/verify/43114.md new file mode 100644 index 0000000..d496e74 --- /dev/null +++ b/verify/43114.md @@ -0,0 +1,1290 @@ +# Avalanche — Deployed Code Verification + +Chain ID: 43114 · Bytecode-proven: **21/21** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0xAf565942…`](https://snowtrace.io/address/0xAf5659428FEF1F6a701FaB46d8f3aF8371A9913D) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `47294620` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0x9ceeD3A7…`](https://snowtrace.io/address/0x9ceeD3A7f753608372eeAb300486cc7c2F38AC68) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `0b021e3f` | ≡ baseline | — | +| eulOFTAdapter | [`0xF1A5F97A…`](https://snowtrace.io/address/0xF1A5F97AB84158Cf6d8ba8dEF68780Fc2Fd64310) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `1036d1c0` | ≡ baseline | — | +| eVaultFactory | [`0xaf4B4c18…`](https://snowtrace.io/address/0xaf4B4c18B17F6a2B32F6c398a3910bdCD7f26181) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0x29E9b639…`](https://snowtrace.io/address/0x29E9b639e165d919FEcf02521F8A9dA0492D4f21) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `8c001272` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0xddcbe30A…`](https://snowtrace.io/address/0xddcbe30A761Edd2e19bba930A977475265F36Fa1) | [`ethereum-vault-connector@a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) | ✅ `b12f6d72` | +58/−11 vs baseline | EVCUtil helper + signer-exclusion hardening | +| oracleRouterFactory | [`0x80528F01…`](https://snowtrace.io/address/0x80528F014E84658e85D3C6D4896A29Fa933Be696) | [`evk-periphery@96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0x8564160f…`](https://snowtrace.io/address/0x8564160f30926eA1229DCcf24118c6De155D2e30) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0x2e3b3273…`](https://snowtrace.io/address/0x2e3b32730B4F6b6502BdAa9122df3B026eDE5391) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0x9C38f923…`](https://snowtrace.io/address/0x9C38f923baC407C818312EADEf69AdC116fd16FD) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0x7e5893f9…`](https://snowtrace.io/address/0x7e5893f9Ad9865261299e543FD3fac814CC11804) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `2fc2cdd1` | +3/−5 vs baseline | formatting only | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0x574B00f5…`](https://snowtrace.io/address/0x574B00f5a0C56D370F19fa887a5545d74F52fAC2) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `c9ee150e` | +18/−18 vs baseline | import-path style only | +| eulerEarnPublicAllocator | [`0x2524762d…`](https://snowtrace.io/address/0x2524762ddb853AB1e572B81E5E6377a8a1536aA5) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV1Factory | [`0x8A1D3a48…`](https://snowtrace.io/address/0x8A1D3a4850ed7deeC9003680Cf41b8E75D27e440) | [`euler-swap@c7da2f33`](https://github.com/euler-xyz/euler-swap/tree/c7da2f330dff3efb98b0b4e998f9b9f498b37c30) | ✅ `f1652049` | +46/−27 vs baseline | licenses/events + solmate import fix | +| eulerSwapV1Implementation | [`0x4F4FDeE3…`](https://snowtrace.io/address/0x4F4FDeE3568aC31C46634fb2Df3FF44A156Be351) | [`euler-swap@c7da2f33`](https://github.com/euler-xyz/euler-swap/tree/c7da2f330dff3efb98b0b4e998f9b9f498b37c30) | ✅ `222485e6` | +46/−27 vs baseline | licenses/events + solmate import fix | +| eulerSwapV1Periphery | [`0x31F34124…`](https://snowtrace.io/address/0x31F34124a37f94efd17201A1B88d5008cD444c72) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `703cfc72` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV2Factory | [`0xd80e68B3…`](https://snowtrace.io/address/0xd80e68B39e4408cb7D6c8E3343Bde46587013F62) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `4bdd5d47` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0x2836825d…`](https://snowtrace.io/address/0x2836825daeC3D5d8fD3ad71d61f72345bB868110) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `408124d9` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0x4fef2f71…`](https://snowtrace.io/address/0x4fef2f7146c0b4e6C0b1433badC6B7a2E1E7ECDb) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `f98bd760` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0x1C0e8b84…`](https://snowtrace.io/address/0x1C0e8b841DA677C685D2a8376773e8A872C1ce5C) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `83e2e2c4` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0xF9f2dF8A…`](https://snowtrace.io/address/0xF9f2dF8A5Cc71a0424dfA9EbdfdfF8A082C19184) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `42c58b74` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0x9507Fe5c4243f5eBd8a7537Fe9272cA48310eaF5` | ✅ | ✅ | +| Token | `0x6999b31d06594e0D1dD8F033d13314d652293738` | ✅ | ✅ | +| Vault | `0xFE61292Fe3CE6e75a3CF6dEB505C38B634BA8667` | ✅ | ✅ | +| Borrowing | `0x00114e33749AA16a6980307B544cbd96C9D23BBa` | ✅ | ✅ | +| Liquidation | `0x48d4B0fE40A2B9D1E965388495df9BB6DcD606C5` | ✅ | ✅ | +| RiskManager | `0xC9EEc20F149345F1Bf07Ce61eA16308c28b14BEe` | ✅ | ✅ | +| BalanceForwarder | `0x1114191AE690d594B1Be45EBdbDD9ff49e6F7dBd` | ✅ | ✅ | +| Governance | `0x73E475D896cBda07D1EeEcE23943CF355Be6159A` | ✅ | ✅ | + +## EulerSwap V2 management implementation (unpacked from the implementation) + +EulerSwap delegatecalls management functions into a separate contract whose address is the public immutable `managementImpl`; it is verified from the same euler-swap pin. + +| Contract | Address | Bytecode | Embedded-immutable cross-check | +|----------|---------|----------|-------------------------------| +| EulerSwapManagement | `0xdF5D946C79131A229F8940713fFAF5789baf6c33` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (EUL): + +Carries the Paladin-audited source revision (natspec blob) — byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnFactory, eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) (eulerSwapV1Periphery): + +Tag eulerswap-1.0 (official V1 release), descendant of the baseline. src delta: SPDX headers UNLICENSED→GPL (14 files) + PR #99 event hoisting (new Events.sol; hook emits Swap with sender). No state-machine or math changes. foundry optimizer_runs raised 10000→1000000 post-audit, pre-deployment. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..ce71a2c 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..39fe65b 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..1befa2e 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {Owned} from "solmate/src/auth/Owned.sol"; +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`c7da2f33`](https://github.com/euler-xyz/euler-swap/tree/c7da2f330dff3efb98b0b4e998f9b9f498b37c30) (eulerSwapV1Factory, eulerSwapV1Implementation): + +Avalanche deployment: public branch fix/solmate-remapping — the eulerswap-1.0 release pin b948f405 plus one commit correcting the solmate import path in utils/ProtocolFee.sol (no code change). Compiled standalone at the repo profile (0.8.27, runs 1000000, shanghai). + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..ce71a2c 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..39fe65b 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..2f55f28 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,7 +1,7 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + +-import {Owned} from "solmate/src/auth/Owned.sol"; ++import {Owned} from "solmate/auth/Owned.sol"; + import {UniswapHook} from "../UniswapHook.sol"; + import {IPoolManager} from "v4-core/interfaces/IPoolManager.sol"; +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (eulOFTAdapter): + +Adapter files blob-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) (evc): + +Descendant of the baseline and the last commit ever to touch src/ on origin/master — the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers — proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding). + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultImplementation + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`f52cb43b`](https://github.com/euler-xyz/euler-price-oracle/tree/f52cb43b587c7fa90a7e722d52698003451feb62)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (rEUL): + +Component files byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (swapVerifier): + +Descendant of the baseline by 3 days (the merge adding the Enigma report PDF). src/Swaps delta is 100% non-semantic forge-fmt re-wrapping. This IS the Enigma-fixes-included state as deployed on 13 chains. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +index b70618d3..d210ab47 100644 +--- a/src/Swaps/MigrationHelper.sol ++++ b/src/Swaps/MigrationHelper.sol +@@ -95,10 +95,7 @@ contract MigrationHelper is EVCUtil { + /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. + /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying + /// the user's permit can only ever drain their own balance. +- function transferBalanceFromSender(address token, uint256 maxAmount, address to) +- external +- returns (uint256 amount) +- { ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) external returns (uint256 amount) { + amount = IERC20(token).balanceOf(_msgSender()); + if (amount > maxAmount) amount = maxAmount; + // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index 23a3c2fd..ec881e76 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -69,7 +69,8 @@ contract SwapVerifier is MigrationHelper { + /// @param receiver The address to transfer the asset to + /// @param amountMin The minimum amount of the asset that must be available before transfer + /// @param deadline A timestamp after which the transfer will revert +- /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if the minimum is met ++ /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if ++ /// the minimum is met + function verifyAmountMinAndTransfer(address asset, address receiver, uint256 amountMin, uint256 deadline) external { + if (deadline < block.timestamp) revert SwapVerifier_pastDeadline(); +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/56.md b/verify/56.md new file mode 100644 index 0000000..1f54aba --- /dev/null +++ b/verify/56.md @@ -0,0 +1,1060 @@ +# BSC — Deployed Code Verification + +Chain ID: 56 · Bytecode-proven: **21/21** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0x2D13C46F…`](https://bscscan.com/address/0x2D13C46FE6c8B6c9ad3C5A78eD51b26733caE350) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `47294620` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0x2117E8b7…`](https://bscscan.com/address/0x2117E8b79e8E176A670c9fCf945d4348556bfFad) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `0b021e3f` | ≡ baseline | — | +| eulOFTAdapter | [`0x16332693…`](https://bscscan.com/address/0x1633269308F154fbECBb15F91d72D2aFA6af95B4) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `1036d1c0` | ≡ baseline | — | +| eVaultFactory | [`0x7F53E275…`](https://bscscan.com/address/0x7F53E2755eB3c43824E162F7F6F087832B9C9Df6) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0xB236413f…`](https://bscscan.com/address/0xB236413f1A8Fd4C5D5545ecAaC5e64fF686afe4e) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `8c001272` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0xb2E5a73C…`](https://bscscan.com/address/0xb2E5a73CeE08593d1a076a2AE7A6e02925a640ea) | [`ethereum-vault-connector@a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) | ✅ `b12f6d72` | +58/−11 vs baseline | EVCUtil helper + signer-exclusion hardening | +| oracleRouterFactory | [`0xbe83f65e…`](https://bscscan.com/address/0xbe83f65e5e898D482FfAEA251B62647c411576F1) | [`evk-periphery@96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0xF524F75a…`](https://bscscan.com/address/0xF524F75ad063919B86d6c5D9242847A44337BFCe) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0x5e13d419…`](https://bscscan.com/address/0x5e13d41913aDF18bb2acAe34228E8D21f3c2f2Eb) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0x7fD287B3…`](https://bscscan.com/address/0x7fD287B3AE3Bf2F6C9871a44b6d9de208B0ABBE5) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0x2d09e4C7…`](https://bscscan.com/address/0x2d09e4C7Ad9c21Cf093046Da69030Dc17d01deFC) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `2fc2cdd1` | +3/−5 vs baseline | formatting only | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0xc456d04E…`](https://bscscan.com/address/0xc456d04E3F43597CC7E5a2AF284fF4C4AdDA0cb1) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `c9ee150e` | +18/−18 vs baseline | import-path style only | +| eulerEarnPublicAllocator | [`0xD5614794…`](https://bscscan.com/address/0xD561479477b03720bF485e91B76574374A646531) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV1Factory | [`0x3e378e5E…`](https://bscscan.com/address/0x3e378e5E339DF5e0Da32964F9EEC2CDb90D28Cc7) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `7c9a247e` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Implementation | [`0x16BCa432…`](https://bscscan.com/address/0x16BCa43290b77409e6D1c92B929f7A09C0E4EE86) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `20cae9a4` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Periphery | [`0xa8826Bb2…`](https://bscscan.com/address/0xa8826Bb29f875Db4c4b482463961776390774525) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `703cfc72` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV2Factory | [`0xA1F83E3d…`](https://bscscan.com/address/0xA1F83E3d1819C912122A1582B4B6D3d2a1E83bb7) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `4bdd5d47` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0x90Cb0b67…`](https://bscscan.com/address/0x90Cb0b67f189a3D914DA00f72070531152DBc85F) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `408124d9` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0x4258A349…`](https://bscscan.com/address/0x4258A34923CccFa29948881Cf6Aa8FdAD6338485) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `f98bd760` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0x71dFB713…`](https://bscscan.com/address/0x71dFB7138192B19CDc73487212bf6BB1Ffe3b9A1) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `83e2e2c4` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0xBc0f4dd9…`](https://bscscan.com/address/0xBc0f4dd9B5A10b15e6fA65e939Dbb1f98E7B08B7) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `42c58b74` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0x653A5b70dA20BDEE19eE58CE671704Bfb418637A` | ✅ | ✅ | +| Token | `0x21ed851E3b5410646C943a93e44182C1E269863B` | ✅ | ✅ | +| Vault | `0xd8dEc06999b0069bbC6e46FD98300427FEB3e51B` | ✅ | ✅ | +| Borrowing | `0xb2bc0D1dce715a13C966Aed067514a846F159cE9` | ✅ | ✅ | +| Liquidation | `0xC34d06c8Ec6cCdBE101F9527bF67439D42F1648A` | ✅ | ✅ | +| RiskManager | `0x3dAa1eD74Bb88D3562079880b24968B03EfE7233` | ✅ | ✅ | +| BalanceForwarder | `0xff58973fC072Dfc8f8B8890E9DF79D69B80df37A` | ✅ | ✅ | +| Governance | `0xCD21AFeAE7084D82347A7ccA8e62AB6AcE3Df7D5` | ✅ | ✅ | + +## EulerSwap V2 management implementation (unpacked from the implementation) + +EulerSwap delegatecalls management functions into a separate contract whose address is the public immutable `managementImpl`; it is verified from the same euler-swap pin. + +| Contract | Address | Bytecode | Embedded-immutable cross-check | +|----------|---------|----------|-------------------------------| +| EulerSwapManagement | `0x88b077130B43a19942c641B66A50418b02D2f7D7` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (EUL): + +Carries the Paladin-audited source revision (natspec blob) — byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnFactory, eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) (eulerSwapV1Factory, eulerSwapV1Implementation, eulerSwapV1Periphery): + +Tag eulerswap-1.0 (official V1 release), descendant of the baseline. src delta: SPDX headers UNLICENSED→GPL (14 files) + PR #99 event hoisting (new Events.sol; hook emits Swap with sender). No state-machine or math changes. foundry optimizer_runs raised 10000→1000000 post-audit, pre-deployment. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..ce71a2c 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..39fe65b 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..1befa2e 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {Owned} from "solmate/src/auth/Owned.sol"; +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (eulOFTAdapter): + +Adapter files blob-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) (evc): + +Descendant of the baseline and the last commit ever to touch src/ on origin/master — the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers — proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding). + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultImplementation + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`f52cb43b`](https://github.com/euler-xyz/euler-price-oracle/tree/f52cb43b587c7fa90a7e722d52698003451feb62)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (rEUL): + +Component files byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (swapVerifier): + +Descendant of the baseline by 3 days (the merge adding the Enigma report PDF). src/Swaps delta is 100% non-semantic forge-fmt re-wrapping. This IS the Enigma-fixes-included state as deployed on 13 chains. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +index b70618d3..d210ab47 100644 +--- a/src/Swaps/MigrationHelper.sol ++++ b/src/Swaps/MigrationHelper.sol +@@ -95,10 +95,7 @@ contract MigrationHelper is EVCUtil { + /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. + /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying + /// the user's permit can only ever drain their own balance. +- function transferBalanceFromSender(address token, uint256 maxAmount, address to) +- external +- returns (uint256 amount) +- { ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) external returns (uint256 amount) { + amount = IERC20(token).balanceOf(_msgSender()); + if (amount > maxAmount) amount = maxAmount; + // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index 23a3c2fd..ec881e76 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -69,7 +69,8 @@ contract SwapVerifier is MigrationHelper { + /// @param receiver The address to transfer the asset to + /// @param amountMin The minimum amount of the asset that must be available before transfer + /// @param deadline A timestamp after which the transfer will revert +- /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if the minimum is met ++ /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if ++ /// the minimum is met + function verifyAmountMinAndTransfer(address asset, address receiver, uint256 amountMin, uint256 deadline) external { + if (deadline < block.timestamp) revert SwapVerifier_pastDeadline(); +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/59144.md b/verify/59144.md new file mode 100644 index 0000000..9312283 --- /dev/null +++ b/verify/59144.md @@ -0,0 +1,1116 @@ +# Linea — Deployed Code Verification + +Chain ID: 59144 · Bytecode-proven: **21/21** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0xB9E491A3…`](https://lineascan.build/address/0xB9E491A3BB9d4B155d31a9cA6B9dE245CA16AAe6) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `8a4340d8` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0x3eBd0148…`](https://lineascan.build/address/0x3eBd0148BADAb9388936E4472C4415D5700478A5) | [`evk-periphery@21a169d7`](https://github.com/euler-xyz/evk-periphery/tree/21a169d7830f71fcfbee6f7ced12bf089f4fba20) | ✅ `d6078fb2` | +1/−1 vs baseline | mint() gains 'virtual' (no behavior change) | +| eulOFTAdapter | [`0xd048d4e3…`](https://lineascan.build/address/0xd048d4e39e13482ECcE115E7BB71128d26ca19f1) | [`evk-periphery@21a169d7`](https://github.com/euler-xyz/evk-periphery/tree/21a169d7830f71fcfbee6f7ced12bf089f4fba20) | ✅ `ee5f5661` | ≡ baseline | — | +| eVaultFactory | [`0x84711986…`](https://lineascan.build/address/0x84711986Fd3BF0bFe4a8e6d7f4E22E67f7f27F04) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `57b01080` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0x58270C41…`](https://lineascan.build/address/0x58270C41552Bb2bef3Dc4e103b6f0c226032f007) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `86133ece` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0xd8CeCEe9…`](https://lineascan.build/address/0xd8CeCEe9A04eA3d941a959F68fb4486f23271d09) | [`ethereum-vault-connector@a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) | ✅ `d1bce236` | +58/−11 vs baseline | EVCUtil helper + signer-exclusion hardening | +| oracleRouterFactory | [`0xf0125F63…`](https://lineascan.build/address/0xf0125F638c7134e6997e4F825b78c324CcF289aF) | [`evk-periphery@21a169d7`](https://github.com/euler-xyz/evk-periphery/tree/21a169d7830f71fcfbee6f7ced12bf089f4fba20) | ✅ `dd195cf0` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0x91868601…`](https://lineascan.build/address/0x91868601df03ED8E134EaAaB5E06F7183CC8383f) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `ae8cce18` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0xe15C5F31…`](https://lineascan.build/address/0xe15C5F31cd7B767883F5654CDD3aFac28966B0a9) | [`evk-periphery@21a169d7`](https://github.com/euler-xyz/evk-periphery/tree/21a169d7830f71fcfbee6f7ced12bf089f4fba20) | ✅ `2068798e` | ≡ baseline | — | +| sequenceRegistry | [`0xcB1bB0A8…`](https://lineascan.build/address/0xcB1bB0A8A7ddeb09983dC1e7F880DCEdc39362BA) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `f8601f0f` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0xd356D057…`](https://lineascan.build/address/0xd356D0570F8Ae45Acf275A09789c67C9E412814e) | [`evk-periphery@e7337a33`](https://github.com/euler-xyz/evk-periphery/tree/e7337a33cb2339de7bf19d41a765c426cfe71be2) | ✅ `69658451` | +3/−5 vs baseline | formatting only | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0x377879A0…`](https://lineascan.build/address/0x377879A039343FEc7564e54616e519328951DA6D) | [`euler-earn@ba581a71`](https://github.com/euler-xyz/euler-earn/tree/ba581a71245ad004d35241918946b08ba63552cd) | ✅ `978dba08` | +5/−4 vs baseline | 24kB fit: setName/setSymbol commented out | +| eulerEarnPublicAllocator | [`0x4148f90e…`](https://lineascan.build/address/0x4148f90e03facFF8D2d5EFb475E36F94b4Ab4994) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `055f4a97` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV1Factory | [`0x970B065B…`](https://lineascan.build/address/0x970B065B572CC0118535Ad1101663CDBE7Db1e21) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `733771fc` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Implementation | [`0x2b07caff…`](https://lineascan.build/address/0x2b07caff83C15c5a70C4C0867DFE7A0BE01025B0) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `85a32379` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Periphery | [`0x0de305aB…`](https://lineascan.build/address/0x0de305aB93902914909951A00079ea1df3FD98eA) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `9b00707e` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV2Factory | [`0xB0cc1D8e…`](https://lineascan.build/address/0xB0cc1D8e6fAc157c76d2c08B7D55Eca1573BcBDF) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `0a646505` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0x476A2ad4…`](https://lineascan.build/address/0x476A2ad4a7c5Ac4DF1CaA429Cb70db865A160c11) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `06ec2a31` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0x57729d78…`](https://lineascan.build/address/0x57729d78650cA751C9dB41f2536cA86da0032351) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `69ef138e` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0xe3ac3685…`](https://lineascan.build/address/0xe3ac3685D607308D4b4e26546EaDf675c37dd3dE) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `e85194c7` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0xEA3050E8…`](https://lineascan.build/address/0xEA3050E8A25f56AD0dbc90C3dCf016d8f5EfFE25) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `507db702` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0x3e5EdC39cB23A56f5e2a21d934e9059042cfE4E9` | ✅ | ✅ | +| Token | `0xCde747b22AE30d9561c62bfCd7B3402643C5ebC8` | ✅ | ✅ | +| Vault | `0x1dbb10d6E49b57e619c119612849CBb97B24E45e` | ✅ | ✅ | +| Borrowing | `0xcB749Fa2250B8ECd4f7039e7cb3185d70B7d6911` | ✅ | ✅ | +| Liquidation | `0xAb92DD463A1AdD2067FAdA5365143818b226401B` | ✅ | ✅ | +| RiskManager | `0xc3616218F7Ef1CEb0888a55a15A5dF5006642c3B` | ✅ | ✅ | +| BalanceForwarder | `0x358D4999cbC4D9943546Cd137671f1fAFc61D461` | ✅ | ✅ | +| Governance | `0x4FBA06Ef56f07035336d568d087f9ece4138839d` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`21a169d7`](https://github.com/euler-xyz/evk-periphery/tree/21a169d7830f71fcfbee6f7ced12bf089f4fba20) (EUL): + +Post-2025-09 revision: same single-keyword delta as above. + +```diff +diff --git a/src/ERC20/deployed/ERC20BurnableMintable.sol b/src/ERC20/deployed/ERC20BurnableMintable.sol +index 82413624..19bb8e81 100644 +--- a/src/ERC20/deployed/ERC20BurnableMintable.sol ++++ b/src/ERC20/deployed/ERC20BurnableMintable.sol +@@ -45,7 +45,7 @@ contract ERC20BurnableMintable is AccessControlEnumerable, ERC20Burnable, ERC20P + /// @notice Mints new tokens and assigns them to an account + /// @param _account The address that will receive the minted tokens + /// @param _amount The amount of tokens to mint +- function mint(address _account, uint256 _amount) external onlyRole(MINTER_ROLE) { ++ function mint(address _account, uint256 _amount) external virtual onlyRole(MINTER_ROLE) { + _mint(_account, _amount); + } +``` + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`ba581a71`](https://github.com/euler-xyz/euler-earn/tree/ba581a71245ad004d35241918946b08ba63552cd) (eulerEarnFactory): + +Linea 24kB size-fit variant (commit on the euler-earn deployment-linea branch, reconstructed from the Lineascan-verified source and bytecode-proven): equals 773453b1 — itself src-identical to the audited baseline — with setName/setSymbol commented out (“commented out not to exceed 24kB limit”) in EulerEarn.sol and IEulerEarn.sol. Deploy-time compile: solc 0.8.26, optimizer_runs 200, evm london, via_ir. + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..103644f 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -190,7 +190,8 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar + } + + /* ONLY OWNER FUNCTIONS */ +- ++// commented out not to exceed 24kB limit ++/* + /// @inheritdoc IEulerEarnBase + function setName(string memory newName) external onlyOwner { + _name = newName; +@@ -204,7 +205,7 @@ contract EulerEarn is ReentrancyGuard, ERC4626, Ownable2Step, EVCUtil, IEulerEar + + emit EventsLib.SetSymbol(newSymbol); + } +- ++*/ + /// @inheritdoc IEulerEarnBase + function setCurator(address newCurator) external onlyOwner { + if (newCurator == curator) revert ErrorsLib.AlreadySet(); +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..c2ee7f7 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -120,10 +120,10 @@ interface IEulerEarnBase { + function revokePendingMarketRemoval(IERC4626 id) external; + + /// @notice Sets the name of the Earn vault. +- function setName(string memory newName) external; ++ //function setName(string memory newName) external; + + /// @notice Sets the symbol of the Earn vault. +- function setSymbol(string memory newSymbol) external; ++ //function setSymbol(string memory newSymbol) external; + + /// @notice Submits a `newGuardian`. + /// @notice Warning: a malicious guardian could disrupt the Earn vault's operation, and would have the power to revoke +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) (eulerSwapV1Factory, eulerSwapV1Implementation, eulerSwapV1Periphery): + +Tag eulerswap-1.0 (official V1 release), descendant of the baseline. src delta: SPDX headers UNLICENSED→GPL (14 files) + PR #99 event hoisting (new Events.sol; hook emits Swap with sender). No state-machine or math changes. foundry optimizer_runs raised 10000→1000000 post-audit, pre-deployment. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..ce71a2c 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..39fe65b 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..1befa2e 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {Owned} from "solmate/src/auth/Owned.sol"; +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`21a169d7`](https://github.com/euler-xyz/evk-periphery/tree/21a169d7830f71fcfbee6f7ced12bf089f4fba20) (eulOFTAdapter): + +Adapter files blob-identical to the baseline (deployment-linea tip). + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) (evc): + +Descendant of the baseline and the last commit ever to touch src/ on origin/master — the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers — proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding). + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultImplementation + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`21a169d7`](https://github.com/euler-xyz/evk-periphery/tree/21a169d7830f71fcfbee6f7ced12bf089f4fba20) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`f52cb43b`](https://github.com/euler-xyz/euler-price-oracle/tree/f52cb43b587c7fa90a7e722d52698003451feb62)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`21a169d7`](https://github.com/euler-xyz/evk-periphery/tree/21a169d7830f71fcfbee6f7ced12bf089f4fba20) (rEUL): + +Component files byte-identical to the baseline (deployment-linea branch tip). + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`e7337a33`](https://github.com/euler-xyz/evk-periphery/tree/e7337a33cb2339de7bf19d41a765c426cfe71be2) (swapVerifier): + +Linea deployment (commit on the evk-periphery deployment-linea-periphery branch, reconstructed from the Lineascan compiler input and bytecode-proven): source byte-identical to edaf96e3 — the Enigma-fixes state — restricted to the SwapVerifier/MigrationHelper compile unit with the deploy settings (0.8.24, runs 10000, london). + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +index b70618d3..d210ab47 100644 +--- a/src/Swaps/MigrationHelper.sol ++++ b/src/Swaps/MigrationHelper.sol +@@ -95,10 +95,7 @@ contract MigrationHelper is EVCUtil { + /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. + /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying + /// the user's permit can only ever drain their own balance. +- function transferBalanceFromSender(address token, uint256 maxAmount, address to) +- external +- returns (uint256 amount) +- { ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) external returns (uint256 amount) { + amount = IERC20(token).balanceOf(_msgSender()); + if (amount > maxAmount) amount = maxAmount; + // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index 23a3c2fd..ec881e76 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -69,7 +69,8 @@ contract SwapVerifier is MigrationHelper { + /// @param receiver The address to transfer the asset to + /// @param amountMin The minimum amount of the asset that must be available before transfer + /// @param deadline A timestamp after which the transfer will revert +- /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if the minimum is met ++ /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if ++ /// the minimum is met + function verifyAmountMinAndTransfer(address asset, address receiver, uint256 amountMin, uint256 deadline) external { + if (deadline < block.timestamp) revert SwapVerifier_pastDeadline(); +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/60808.md b/verify/60808.md new file mode 100644 index 0000000..7334c37 --- /dev/null +++ b/verify/60808.md @@ -0,0 +1,1070 @@ +# BOB — Deployed Code Verification + +Chain ID: 60808 · Bytecode-proven: **21/21** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0x5a3828be…`](https://explorer.gobob.xyz/address/0x5a3828beA292E5f29725Fa449F9113Cb5E60ADF8) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `47294620` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0xDe1763aF…`](https://explorer.gobob.xyz/address/0xDe1763aFA5eB658CfFFfD16835AfeB47e7aC0B8D) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `0b021e3f` | ≡ baseline | — | +| eulOFTAdapter | [`0x797964F9…`](https://explorer.gobob.xyz/address/0x797964F9eB3A733D443810820f56c9ebAab1d1c2) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `1036d1c0` | ≡ baseline | — | +| eVaultFactory | [`0x046a9837…`](https://explorer.gobob.xyz/address/0x046a9837A61d6b6263f54F4E27EE072bA4bdC7e4) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0x32CFc569…`](https://explorer.gobob.xyz/address/0x32CFc56917C0025501b34C43f7FE767Ef1EDE3a2) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `8c001272` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0x59f0FeEc…`](https://explorer.gobob.xyz/address/0x59f0FeEc4fA474Ad4ffC357cC8d8595B68abE47d) | [`ethereum-vault-connector@a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) | ✅ `b12f6d72` | +58/−11 vs baseline | EVCUtil helper + signer-exclusion hardening | +| oracleRouterFactory | [`0xEFCF1F2f…`](https://explorer.gobob.xyz/address/0xEFCF1F2f09163e3813f5C16346A9F2Aa21ABA74d) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0x94047C7d…`](https://explorer.gobob.xyz/address/0x94047C7daF06a6DE4049365cFa95fb4389a6F9Fe) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0x9f395F61…`](https://explorer.gobob.xyz/address/0x9f395F610Af9ffC98693A0769190446180dc7192) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0xf4C09771…`](https://explorer.gobob.xyz/address/0xf4C097718c64B6B0A75Cd9e0EF348fD6F176bE67) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0x585DAE97…`](https://explorer.gobob.xyz/address/0x585DAE976333DF77ec096c3BcEf1EBEC296476a4) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `2fc2cdd1` | +3/−5 vs baseline | formatting only | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0x8F01c664…`](https://explorer.gobob.xyz/address/0x8F01c6640A1c0a6085C79843F861fF0F89b9fED6) | [`euler-earn@773453b1`](https://github.com/euler-xyz/euler-earn/tree/773453b1f4a6f1d27a1cd0c6d8f6ada572503b23) | ✅ `c9ee150e` | ≡ baseline | — | +| eulerEarnPublicAllocator | [`0xB5Daee4a…`](https://explorer.gobob.xyz/address/0xB5Daee4a8AD1388B3D72C1367b8BA63DfB4AAbf5) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV1Factory | [`0xE25B3cdA…`](https://explorer.gobob.xyz/address/0xE25B3cdA6fccAcbD794aEA64eE1B496d7b441644) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `7c9a247e` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Implementation | [`0x334eac29…`](https://explorer.gobob.xyz/address/0x334eac29ffAc27E6BC3484A738DAf520359698F0) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `20cae9a4` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Periphery | [`0x199cC7C8…`](https://explorer.gobob.xyz/address/0x199cC7C8606088bc22D82CDae2D7EE7F5F99ec9F) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `703cfc72` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV2Factory | [`0xa077991e…`](https://explorer.gobob.xyz/address/0xa077991e2929d97f29fE39372E736FC118a4FAd3) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `4bdd5d47` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0x90bd38E8…`](https://explorer.gobob.xyz/address/0x90bd38E89726BdCf42E07D88B23c2A493cb3877a) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `408124d9` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0xaEAab95e…`](https://explorer.gobob.xyz/address/0xaEAab95eE90196E20fD2a5348643cCa0EF2b038e) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `f98bd760` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0x6e5dF960…`](https://explorer.gobob.xyz/address/0x6e5dF960eccD2Bf8818526A88f6E7da99a5379d7) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `83e2e2c4` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0xf33F4e20…`](https://explorer.gobob.xyz/address/0xf33F4e20905801D55531b38749727954D0152d3D) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `42c58b74` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0x3F30769dD4A7279e25e55B7754a73F619eD27712` | ✅ | ✅ | +| Token | `0x3036d20f8497684D170bEbF6AE697Dc9852b527b` | ✅ | ✅ | +| Vault | `0xC9A7FB176F8e24B663c988dC2AFF3B901D5e1455` | ✅ | ✅ | +| Borrowing | `0x90c108f0C3CD493C3b21376D7efc65875300b0D6` | ✅ | ✅ | +| Liquidation | `0x5d04bE5E51d7f3E39A6bbC626A40D3f5C3A66e97` | ✅ | ✅ | +| RiskManager | `0x0786E20EBAa5a5C46d3f5E85ab1981D582996eb0` | ✅ | ✅ | +| BalanceForwarder | `0x2011D7C69104795D85d2ce958F20b5cA1a6210Fa` | ✅ | ✅ | +| Governance | `0x11a4730e0eB5fEb7eDD46F53709c12aDCfc3cAa1` | ✅ | ✅ | + +## EulerSwap V2 management implementation (unpacked from the implementation) + +EulerSwap delegatecalls management functions into a separate contract whose address is the public immutable `managementImpl`; it is verified from the same euler-swap pin. + +| Contract | Address | Bytecode | Embedded-immutable cross-check | +|----------|---------|----------|-------------------------------| +| EulerSwapManagement | `0xa247F3c6b61b3a65714bC2F63b2A683241dCe643` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (EUL): + +Carries the Paladin-audited source revision (natspec blob) — byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`773453b1`](https://github.com/euler-xyz/euler-earn/tree/773453b1f4a6f1d27a1cd0c6d8f6ada572503b23) (eulerEarnFactory): + +src/ identical to the baseline (empty diff). + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) (eulerSwapV1Factory, eulerSwapV1Implementation, eulerSwapV1Periphery): + +Tag eulerswap-1.0 (official V1 release), descendant of the baseline. src delta: SPDX headers UNLICENSED→GPL (14 files) + PR #99 event hoisting (new Events.sol; hook emits Swap with sender). No state-machine or math changes. foundry optimizer_runs raised 10000→1000000 post-audit, pre-deployment. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..ce71a2c 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..39fe65b 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..1befa2e 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {Owned} from "solmate/src/auth/Owned.sol"; +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (eulOFTAdapter): + +Adapter files blob-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) (evc): + +Descendant of the baseline and the last commit ever to touch src/ on origin/master — the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers — proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding). + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultImplementation + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`abfbfc9f`](https://github.com/euler-xyz/euler-price-oracle/tree/abfbfc9fa3a7c74024df3a75be48282fce5e15ae)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (rEUL): + +Component files byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (swapVerifier): + +Descendant of the baseline by 3 days (the merge adding the Enigma report PDF). src/Swaps delta is 100% non-semantic forge-fmt re-wrapping. This IS the Enigma-fixes-included state as deployed on 13 chains. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +index b70618d3..d210ab47 100644 +--- a/src/Swaps/MigrationHelper.sol ++++ b/src/Swaps/MigrationHelper.sol +@@ -95,10 +95,7 @@ contract MigrationHelper is EVCUtil { + /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. + /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying + /// the user's permit can only ever drain their own balance. +- function transferBalanceFromSender(address token, uint256 maxAmount, address to) +- external +- returns (uint256 amount) +- { ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) external returns (uint256 amount) { + amount = IERC20(token).balanceOf(_msgSender()); + if (amount > maxAmount) amount = maxAmount; + // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index 23a3c2fd..ec881e76 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -69,7 +69,8 @@ contract SwapVerifier is MigrationHelper { + /// @param receiver The address to transfer the asset to + /// @param amountMin The minimum amount of the asset that must be available before transfer + /// @param deadline A timestamp after which the transfer will revert +- /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if the minimum is met ++ /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if ++ /// the minimum is met + function verifyAmountMinAndTransfer(address asset, address receiver, uint256 amountMin, uint256 deadline) external { + if (deadline < block.timestamp) revert SwapVerifier_pastDeadline(); +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/80094.md b/verify/80094.md new file mode 100644 index 0000000..2c60abc --- /dev/null +++ b/verify/80094.md @@ -0,0 +1,1070 @@ +# Berachain — Deployed Code Verification + +Chain ID: 80094 · Bytecode-proven: **21/21** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0x70Fb24bD…`](https://berascan.com/address/0x70Fb24bDa46E7cFD447C64bB32180Bc746ba3A71) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `47294620` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0xEb9b5f4E…`](https://berascan.com/address/0xEb9b5f4EB023aE754fF59A04c9C038D58606DAC6) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `0b021e3f` | ≡ baseline | — | +| eulOFTAdapter | [`0xc1d31b28…`](https://berascan.com/address/0xc1d31b2812Cc920341349a717d14bAdFb1BCab11) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `1036d1c0` | ≡ baseline | — | +| eVaultFactory | [`0x5C13fb43…`](https://berascan.com/address/0x5C13fb43ae9BAe8470f646ea647784534E9543AF) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0x402598Ac…`](https://berascan.com/address/0x402598Ac4034D24f2cB37BDb0721A67365aD19BD) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `8c001272` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0x45334608…`](https://berascan.com/address/0x45334608ECE7B2775136bC847EB92B5D332806A9) | [`ethereum-vault-connector@a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) | ✅ `b12f6d72` | +58/−11 vs baseline | EVCUtil helper + signer-exclusion hardening | +| oracleRouterFactory | [`0x809aB347…`](https://berascan.com/address/0x809aB347e6ECb46714917A7796E542c86f75FbF1) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0x51432af6…`](https://berascan.com/address/0x51432af61A715DB3D0f20A3691C1E25F9A2c6B05) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0x56C44d2F…`](https://berascan.com/address/0x56C44d2F484A61ce92Fa0BCc849feB37aBfeB59C) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0x0c9a75E0…`](https://berascan.com/address/0x0c9a75E05764775A0cF52bC6cbfE6Cb229bb3901) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0x562ADb2d…`](https://berascan.com/address/0x562ADb2d72C1836621B2E82bCb7599DFE9578203) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `2fc2cdd1` | +3/−5 vs baseline | formatting only | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0x9cbc3030…`](https://berascan.com/address/0x9cbc3030e6d133D1AAa148D598FD82D70263495c) | [`euler-earn@773453b1`](https://github.com/euler-xyz/euler-earn/tree/773453b1f4a6f1d27a1cd0c6d8f6ada572503b23) | ✅ `c9ee150e` | ≡ baseline | — | +| eulerEarnPublicAllocator | [`0x4E7C0590…`](https://berascan.com/address/0x4E7C059099496D56e8662570426991EA63C63C85) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV1Factory | [`0xD14c95dc…`](https://berascan.com/address/0xD14c95dc228E8851F63d9b83A0001F4D021B5DFf) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `7c9a247e` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Implementation | [`0x0e05d236…`](https://berascan.com/address/0x0e05d236cb6c350935751A73e834A13111998e3c) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `20cae9a4` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Periphery | [`0x46F95127…`](https://berascan.com/address/0x46F951278f52f4798542C51BfB8Df1c165199150) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `703cfc72` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV2Factory | [`0x1A4546b9…`](https://berascan.com/address/0x1A4546b988Ee133F72b7E27a4890355b0a341554) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `4bdd5d47` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0x9253a3EF…`](https://berascan.com/address/0x9253a3EF2cE8875b7D15Bd2bcd3a405b62a7b0E7) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `408124d9` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0x5e044DB2…`](https://berascan.com/address/0x5e044DB2Fd14fbB48334b239CfD8530C9b03150B) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `f98bd760` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0xAe26ca82…`](https://berascan.com/address/0xAe26ca82da91a1157E3cC0B36a9A06f539f4DF24) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `83e2e2c4` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0x8D8B81F0…`](https://berascan.com/address/0x8D8B81F0c1be01fa3636d2cD6DeF07474d75e1e9) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `42c58b74` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0x50a263439b7701510b48E2D5D89A23e4f78EC8a3` | ✅ | ✅ | +| Token | `0x55772FeAD5EE157246b5B37bEbB7B9afAfdc8612` | ✅ | ✅ | +| Vault | `0xcD6830cFbf61d291ECB4501eA461CF2f8FC1dF65` | ✅ | ✅ | +| Borrowing | `0x6438cd2367dE1eE149E126b2d6D2e5E30a5Be648` | ✅ | ✅ | +| Liquidation | `0x94Bf58695beb2B9CcbD6a92355099f0E23c1F78B` | ✅ | ✅ | +| RiskManager | `0xFbD886Ad4D097e3c8d8835eedc2a76252c8CeE1a` | ✅ | ✅ | +| BalanceForwarder | `0x79ACe43986A358b2EBb178F31Ec9923CCDdBf029` | ✅ | ✅ | +| Governance | `0xa86C1C45A089b7d1a9543f0DcAc037ea27B98745` | ✅ | ✅ | + +## EulerSwap V2 management implementation (unpacked from the implementation) + +EulerSwap delegatecalls management functions into a separate contract whose address is the public immutable `managementImpl`; it is verified from the same euler-swap pin. + +| Contract | Address | Bytecode | Embedded-immutable cross-check | +|----------|---------|----------|-------------------------------| +| EulerSwapManagement | `0x09857c93566359bbcfA0a16aFA9B55eB1D89c9aD` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (EUL): + +Carries the Paladin-audited source revision (natspec blob) — byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`773453b1`](https://github.com/euler-xyz/euler-earn/tree/773453b1f4a6f1d27a1cd0c6d8f6ada572503b23) (eulerEarnFactory): + +src/ identical to the baseline (empty diff). + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) (eulerSwapV1Factory, eulerSwapV1Implementation, eulerSwapV1Periphery): + +Tag eulerswap-1.0 (official V1 release), descendant of the baseline. src delta: SPDX headers UNLICENSED→GPL (14 files) + PR #99 event hoisting (new Events.sol; hook emits Swap with sender). No state-machine or math changes. foundry optimizer_runs raised 10000→1000000 post-audit, pre-deployment. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..ce71a2c 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..39fe65b 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..1befa2e 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {Owned} from "solmate/src/auth/Owned.sol"; +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (eulOFTAdapter): + +Adapter files blob-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) (evc): + +Descendant of the baseline and the last commit ever to touch src/ on origin/master — the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers — proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding). + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultImplementation + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`abfbfc9f`](https://github.com/euler-xyz/euler-price-oracle/tree/abfbfc9fa3a7c74024df3a75be48282fce5e15ae)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (rEUL): + +Component files byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (swapVerifier): + +Descendant of the baseline by 3 days (the merge adding the Enigma report PDF). src/Swaps delta is 100% non-semantic forge-fmt re-wrapping. This IS the Enigma-fixes-included state as deployed on 13 chains. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +index b70618d3..d210ab47 100644 +--- a/src/Swaps/MigrationHelper.sol ++++ b/src/Swaps/MigrationHelper.sol +@@ -95,10 +95,7 @@ contract MigrationHelper is EVCUtil { + /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. + /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying + /// the user's permit can only ever drain their own balance. +- function transferBalanceFromSender(address token, uint256 maxAmount, address to) +- external +- returns (uint256 amount) +- { ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) external returns (uint256 amount) { + amount = IERC20(token).balanceOf(_msgSender()); + if (amount > maxAmount) amount = maxAmount; + // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index 23a3c2fd..ec881e76 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -69,7 +69,8 @@ contract SwapVerifier is MigrationHelper { + /// @param receiver The address to transfer the asset to + /// @param amountMin The minimum amount of the asset that must be available before transfer + /// @param deadline A timestamp after which the transfer will revert +- /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if the minimum is met ++ /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if ++ /// the minimum is met + function verifyAmountMinAndTransfer(address asset, address receiver, uint256 amountMin, uint256 deadline) external { + if (deadline < block.timestamp) revert SwapVerifier_pastDeadline(); +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/8453.md b/verify/8453.md new file mode 100644 index 0000000..2b7dbe6 --- /dev/null +++ b/verify/8453.md @@ -0,0 +1,988 @@ +# Base — Deployed Code Verification + +Chain ID: 8453 · Bytecode-proven: **21/21** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0x029fDEe8…`](https://basescan.org/address/0x029fDEe85BEdB0553D6fdc538546586641DD7438) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `48762e01` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0xa153Ad73…`](https://basescan.org/address/0xa153Ad732F831a79b5575Fa02e793EC4E99181b0) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `0b021e3f` | ≡ baseline | — | +| eulOFTAdapter | [`0x9ff7ea0C…`](https://basescan.org/address/0x9ff7ea0Cf94b8665c2F5d17560Bd34Ab9BbAcd21) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `1036d1c0` | ≡ baseline | — | +| eVaultFactory | [`0x7F321498…`](https://basescan.org/address/0x7F321498A801A191a93C840750ed637149dDf8D0) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0x30a9A965…`](https://basescan.org/address/0x30a9A9654804F1e5b3291a86E83EdeD7cF281618) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `8c001272` | +1/−1 vs baseline | one fee-share default parameter | +| evc | [`0x5301c7dD…`](https://basescan.org/address/0x5301c7dD20bD945D2013b48ed0DEE3A284ca8989) | [`ethereum-vault-connector@a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) | ✅ `b12f6d72` | +58/−11 vs baseline | EVCUtil helper + signer-exclusion hardening | +| oracleRouterFactory | [`0xA9287853…`](https://basescan.org/address/0xA9287853987B107969f181Cce5e25e0D09c1c116) | [`evk-periphery@96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0x1D4b9e6A…`](https://basescan.org/address/0x1D4b9e6ACACdc82Dd9E903C3F4431558Af32C4A9) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0xE08e1f00…`](https://basescan.org/address/0xE08e1f00D388E201e48842E53fA96195568e6813) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0xfE9011FD…`](https://basescan.org/address/0xfE9011FD097cd35866b9e4740BBC88B4ef26E3ba) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0x93A732A1…`](https://basescan.org/address/0x93A732A1900697d5f51C77fe09275486BB0bb83D) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `2fc2cdd1` | +3/−5 vs baseline | formatting only | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0x75F49a26…`](https://basescan.org/address/0x75F49a2621b6DeC6a5baB22ce961bF3e676EFAE6) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `c9ee150e` | +18/−18 vs baseline | import-path style only | +| eulerEarnPublicAllocator | [`0x0dFFc3A5…`](https://basescan.org/address/0x0dFFc3A53693bCd8e42FAd9be94fB8f1Fb64A8EE) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV1Factory | [`0xf0CFe22d…`](https://basescan.org/address/0xf0CFe22d23699ff1B2CFe6B8f706A6DB63911262) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `7c9a247e` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Implementation | [`0x3Ce63C16…`](https://basescan.org/address/0x3Ce63C16CB719a0c755DA25cd5dD35170A00424f) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `20cae9a4` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Periphery | [`0x18e5F5C1…`](https://basescan.org/address/0x18e5F5C1ff5e905b32CE860576031AE90E1d1336) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `703cfc72` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV2Factory | [`0x6C5f4c23…`](https://basescan.org/address/0x6C5f4c239ceD289447737EAB8eEA64523bd9c05E) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `4bdd5d47` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0x6F1C1a3e…`](https://basescan.org/address/0x6F1C1a3eAFbB1b345AD5662b0374a9Bf0E4785af) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `408124d9` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0xA564dAe6…`](https://basescan.org/address/0xA564dAe65eA7B1ce049AbACFC4Cb1A32C93e127c) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `f98bd760` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0x78bCCFA3…`](https://basescan.org/address/0x78bCCFA312432cE84d0B818796eE33f9192A284d) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `83e2e2c4` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0x35D410A5…`](https://basescan.org/address/0x35D410A5052c7362eCdD72cFb65651A71adFaf61) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `42c58b74` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0x9c387d74a4776Ada95c238327ABD03D9E2bc6e5E` | ✅ | ✅ | +| Token | `0xD93F50167b20e7767748D1da102d3dD6f98C7e5B` | ✅ | ✅ | +| Vault | `0x1C376866039Aad238B3Ae977d28C02531B911f8A` | ✅ | ✅ | +| Borrowing | `0xDf01f496Fd1D916D7BD8B875Ee1e008fcc1C38F6` | ✅ | ✅ | +| Liquidation | `0xc0F9b68290fe6D3d33347F1BEb89a724109A4f5a` | ✅ | ✅ | +| RiskManager | `0xE01F74E6934Fe4Ff621547AAa63C3e2f7Ace7c68` | ✅ | ✅ | +| BalanceForwarder | `0xAF47731ee17dFCd04B20C390F843DDDD3598d647` | ✅ | ✅ | +| Governance | `0xc5e04Ed147E2F57c121aA9031729FfDC00a0a340` | ✅ | ✅ | + +## EulerSwap V2 management implementation (unpacked from the implementation) + +EulerSwap delegatecalls management functions into a separate contract whose address is the public immutable `managementImpl`; it is verified from the same euler-swap pin. + +| Contract | Address | Bytecode | Embedded-immutable cross-check | +|----------|---------|----------|-------------------------------| +| EulerSwapManagement | `0x4f1100EEEAEf297944a72aB29B149aABd9eb5796` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (EUL): + +Carries the Paladin-audited source revision (natspec blob) — byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnFactory, eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) (eulerSwapV1Factory, eulerSwapV1Implementation, eulerSwapV1Periphery): + +Tag eulerswap-1.0 (official V1 release), descendant of the baseline. src delta: SPDX headers UNLICENSED→GPL (14 files) + PR #99 event hoisting (new Events.sol; hook emits Swap with sender). No state-machine or math changes. foundry optimizer_runs raised 10000→1000000 post-audit, pre-deployment. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..ce71a2c 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..39fe65b 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..1befa2e 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {Owned} from "solmate/src/auth/Owned.sol"; +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (eulOFTAdapter): + +Adapter files blob-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) (evc): + +Descendant of the baseline and the last commit ever to touch src/ on origin/master — the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers — proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding). + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, eVaultImplementation, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`96b83f80`](https://github.com/euler-xyz/evk-periphery/tree/96b83f80ded9ac3f28bfce871b55917e360b9159) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`f52cb43b`](https://github.com/euler-xyz/euler-price-oracle/tree/f52cb43b587c7fa90a7e722d52698003451feb62)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (rEUL): + +Component files byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (swapVerifier): + +Descendant of the baseline by 3 days (the merge adding the Enigma report PDF). src/Swaps delta is 100% non-semantic forge-fmt re-wrapping. This IS the Enigma-fixes-included state as deployed on 13 chains. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +index b70618d3..d210ab47 100644 +--- a/src/Swaps/MigrationHelper.sol ++++ b/src/Swaps/MigrationHelper.sol +@@ -95,10 +95,7 @@ contract MigrationHelper is EVCUtil { + /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. + /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying + /// the user's permit can only ever drain their own balance. +- function transferBalanceFromSender(address token, uint256 maxAmount, address to) +- external +- returns (uint256 amount) +- { ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) external returns (uint256 amount) { + amount = IERC20(token).balanceOf(_msgSender()); + if (amount > maxAmount) amount = maxAmount; + // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index 23a3c2fd..ec881e76 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -69,7 +69,8 @@ contract SwapVerifier is MigrationHelper { + /// @param receiver The address to transfer the asset to + /// @param amountMin The minimum amount of the asset that must be available before transfer + /// @param deadline A timestamp after which the transfer will revert +- /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if the minimum is met ++ /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if ++ /// the minimum is met + function verifyAmountMinAndTransfer(address asset, address receiver, uint256 amountMin, uint256 deadline) external { + if (deadline < block.timestamp) revert SwapVerifier_pastDeadline(); +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/9745.md b/verify/9745.md new file mode 100644 index 0000000..53db3d2 --- /dev/null +++ b/verify/9745.md @@ -0,0 +1,1060 @@ +# Plasma — Deployed Code Verification + +Chain ID: 9745 · Bytecode-proven: **21/21** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0x6e6e1e4F…`](https://plasmascan.to/address/0x6e6e1e4FB3Ee6C074f10d3f80E0d3541accf7c2b) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `47294620` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0xca632FA5…`](https://plasmascan.to/address/0xca632FA58397391C750c13F935DAA61AbBe0BaA6) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `0b021e3f` | ≡ baseline | — | +| eulOFTAdapter | [`0x78F50C52…`](https://plasmascan.to/address/0x78F50C520E7fCE30410516B72A48bD4fc5d974b5) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `1036d1c0` | ≡ baseline | — | +| eVaultFactory | [`0x42388213…`](https://plasmascan.to/address/0x42388213C6F56D7E1477632b58Ae6Bba9adeEeA3) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0x8346BeBa…`](https://plasmascan.to/address/0x8346BeBaA0789Eb92CFfCC07033b8bF9f3eFdcAB) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `8c001272` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0x7bdbd0A7…`](https://plasmascan.to/address/0x7bdbd0A7114aA42CA957F292145F6a931a345583) | [`ethereum-vault-connector@a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) | ✅ `b12f6d72` | +58/−11 vs baseline | EVCUtil helper + signer-exclusion hardening | +| oracleRouterFactory | [`0x7e539159…`](https://plasmascan.to/address/0x7e539159a06CFe0A9f855d22dD82aD95eDf8C2F1) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0x593Ab8A0…`](https://plasmascan.to/address/0x593Ab8A0182f752c6f1af52CA2A0E8B9F868f64A) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0xe2011F2b…`](https://plasmascan.to/address/0xe2011F2bF6556863c3bacE991Efc8DaC26CD84c2) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0x3cf6e4c1…`](https://plasmascan.to/address/0x3cf6e4c11333b30f0D0CEAe6B78f53a660df357c) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0x84Fd34E9…`](https://plasmascan.to/address/0x84Fd34E9dd12f8D6Cb884f93277d146BDbDF35B5) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `2fc2cdd1` | +3/−5 vs baseline | formatting only | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0xA3843A73…`](https://plasmascan.to/address/0xA3843A73e6a9F81309B931237Ca4759B3B02ff0E) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `c9ee150e` | +18/−18 vs baseline | import-path style only | +| eulerEarnPublicAllocator | [`0x667aD135…`](https://plasmascan.to/address/0x667aD135188d95a32A4E743Aebe5a5b503cb9038) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV1Factory | [`0xD7aA0310…`](https://plasmascan.to/address/0xD7aA03104c2CCaC58acB00CbE90865FA64BbE77D) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `7c9a247e` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Implementation | [`0x7F6ff62e…`](https://plasmascan.to/address/0x7F6ff62e7ECED715a2f4E5Ebe14eC9d32a44EFDc) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `20cae9a4` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV1Periphery | [`0x1472ebB0…`](https://plasmascan.to/address/0x1472ebB000190275B5e28733e45a2614F1C3F41C) | [`euler-swap@b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) | ✅ `703cfc72` | +45/−26 vs baseline | SPDX licenses + event hoisting | +| eulerSwapV2Factory | [`0x29FAFDbf…`](https://plasmascan.to/address/0x29FAFDbf952e7b5c0A6Cd26957829334d54E872A) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `4bdd5d47` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0xdAdBb7a0…`](https://plasmascan.to/address/0xdAdBb7a06638e3345A341002e956324A46d1c28c) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `408124d9` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0x741Fc7A9…`](https://plasmascan.to/address/0x741Fc7A904c9F810cbc4a21DE7D07B51B5Da853C) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `f98bd760` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0x8ec298B4…`](https://plasmascan.to/address/0x8ec298B473D17e04F819453C72747c3d4d6B7848) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `83e2e2c4` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0x8D6A81Ec…`](https://plasmascan.to/address/0x8D6A81Ec8f5680849dCFBa47c710Dd9DA02aDaea) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `42c58b74` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0xA4d3A7A4E56ECB154127A0f18b1850c2d1dbfAB0` | ✅ | ✅ | +| Token | `0xcaAB6E473766C5aC75117dF3663AA96eEe3E89c5` | ✅ | ✅ | +| Vault | `0x7A8Bc44dB0311a8216Ca39E56Ee7F458a71BAaF8` | ✅ | ✅ | +| Borrowing | `0x00D7a88D77083f4334620dA883568374a0159A12` | ✅ | ✅ | +| Liquidation | `0x82e391144B0eb8eDa23d1ccDC1B7EfFB20742bC1` | ✅ | ✅ | +| RiskManager | `0x806107a55e23C957b046eDd0809b4306dB54c266` | ✅ | ✅ | +| BalanceForwarder | `0xd29492adE8660727bCe621d4926a05461322520d` | ✅ | ✅ | +| Governance | `0xA1E475efb83e5196C3026283f33A1535bA1d3c83` | ✅ | ✅ | + +## EulerSwap V2 management implementation (unpacked from the implementation) + +EulerSwap delegatecalls management functions into a separate contract whose address is the public immutable `managementImpl`; it is verified from the same euler-swap pin. + +| Contract | Address | Bytecode | Embedded-immutable cross-check | +|----------|---------|----------|-------------------------------| +| EulerSwapManagement | `0x4E2f910af7e935c3A1BF2a1D7865DAd926f591A8` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (EUL): + +Carries the Paladin-audited source revision (natspec blob) — byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnFactory, eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v1 — baseline `207524c5` ([Cyfrin (`cyfrin-euler-swap-2025`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf)) + +_Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits — 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them._ + +Deployed pin [`b948f405`](https://github.com/euler-xyz/euler-swap/tree/b948f4052d7ab3116235ec754368b7125dbd5082) (eulerSwapV1Factory, eulerSwapV1Implementation, eulerSwapV1Periphery): + +Tag eulerswap-1.0 (official V1 release), descendant of the baseline. src delta: SPDX headers UNLICENSED→GPL (14 files) + PR #99 event hoisting (new Events.sol; hook emits Swap with sender). No state-machine or math changes. foundry optimizer_runs raised 10000→1000000 post-audit, pre-deployment. + +```diff +diff --git a/src/EulerSwap.sol b/src/EulerSwap.sol +index 88ddc53..9953a0b 100644 +--- a/src/EulerSwap.sol ++++ b/src/EulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol"; +@@ -9,6 +9,7 @@ import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; + import {UniswapHook} from "./UniswapHook.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {FundsLib} from "./libraries/FundsLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -17,18 +18,6 @@ import {QuoteLib} from "./libraries/QuoteLib.sol"; + contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook { + bytes32 public constant curve = bytes32("EulerSwap v1"); + +- event EulerSwapActivated(address indexed asset0, address indexed asset1); +- event Swap( +- address indexed sender, +- uint256 amount0In, +- uint256 amount1In, +- uint256 amount0Out, +- uint256 amount1Out, +- uint112 reserve0, +- uint112 reserve1, +- address indexed to +- ); +- + error Locked(); + error AlreadyActivated(); + error BadParam(); +diff --git a/src/EulerSwapFactory.sol b/src/EulerSwapFactory.sol +index 6c9650d..755c05b 100644 +--- a/src/EulerSwapFactory.sol ++++ b/src/EulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; +diff --git a/src/EulerSwapPeriphery.sol b/src/EulerSwapPeriphery.sol +index 91073ca..6929e94 100644 +--- a/src/EulerSwapPeriphery.sol ++++ b/src/EulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/Events.sol b/src/Events.sol +new file mode 100644 +index 0000000..1fc7c5c +--- /dev/null ++++ b/src/Events.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++pragma solidity ^0.8.27; ++ ++/// @notice Emitted upon EulerSwap instance creation. ++/// * `asset0` and `asset1` are the underlying assets of the vaults. ++/// They are always in lexical order: `asset0 < asset1`. ++event EulerSwapActivated(address indexed asset0, address indexed asset1); ++ ++/// @notice Emitted after every swap. ++/// * `sender` is the initiator of the swap, or the Router when invoked via hook. ++/// * `amount0In` and `amount1In` are after fees have been subtracted. ++/// * `reserve0` and `reserve1` are the pool's new reserves (after the swap). ++/// * `to` is the specified recipient of the funds, or the PoolManager when invoked via hook. ++event Swap( ++ address indexed sender, ++ uint256 amount0In, ++ uint256 amount1In, ++ uint256 amount0Out, ++ uint256 amount1Out, ++ uint112 reserve0, ++ uint112 reserve1, ++ address indexed to ++); +diff --git a/src/UniswapHook.sol b/src/UniswapHook.sol +index 229a61f..6014d90 100644 +--- a/src/UniswapHook.sol ++++ b/src/UniswapHook.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +@@ -15,6 +15,7 @@ import { + import {IEVault} from "evk/EVault/IEVault.sol"; + + import {IEulerSwap} from "./interfaces/IEulerSwap.sol"; ++import "./Events.sol"; + import {CtxLib} from "./libraries/CtxLib.sol"; + import {QuoteLib} from "./libraries/QuoteLib.sol"; + import {CurveLib} from "./libraries/CurveLib.sol"; +@@ -79,7 +80,7 @@ contract UniswapHook is BaseHook { + } + } + +- function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) ++ function _beforeSwap(address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata) + internal + override + nonReentrantHook +@@ -135,6 +136,12 @@ contract UniswapHook is BaseHook { + + s.reserve0 = uint112(newReserve0); + s.reserve1 = uint112(newReserve1); ++ ++ if (params.zeroForOne) { ++ emit Swap(sender, amountInWithoutFee, 0, 0, amountOut, s.reserve0, s.reserve1, msg.sender); ++ } else { ++ emit Swap(sender, 0, amountInWithoutFee, amountOut, 0, s.reserve0, s.reserve1, msg.sender); ++ } + } + + return (BaseHook.beforeSwap.selector, returnDelta, 0); +diff --git a/src/interfaces/IEulerSwap.sol b/src/interfaces/IEulerSwap.sol +index 20d0a10..ce71a2c 100644 +--- a/src/interfaces/IEulerSwap.sol ++++ b/src/interfaces/IEulerSwap.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwap { +diff --git a/src/interfaces/IEulerSwapCallee.sol b/src/interfaces/IEulerSwapCallee.sol +index 32f7d7a..1a9cc26 100644 +--- a/src/interfaces/IEulerSwapCallee.sol ++++ b/src/interfaces/IEulerSwapCallee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapCallee { +diff --git a/src/interfaces/IEulerSwapFactory.sol b/src/interfaces/IEulerSwapFactory.sol +index bdd4c34..9c92086 100644 +--- a/src/interfaces/IEulerSwapFactory.sol ++++ b/src/interfaces/IEulerSwapFactory.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + import {IEulerSwap} from "./IEulerSwap.sol"; +diff --git a/src/interfaces/IEulerSwapPeriphery.sol b/src/interfaces/IEulerSwapPeriphery.sol +index bc9337a..39fe65b 100644 +--- a/src/interfaces/IEulerSwapPeriphery.sol ++++ b/src/interfaces/IEulerSwapPeriphery.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: MIT + pragma solidity >=0.8.0; + + interface IEulerSwapPeriphery { +diff --git a/src/libraries/CtxLib.sol b/src/libraries/CtxLib.sol +index ed11e77..d115be9 100644 +--- a/src/libraries/CtxLib.sol ++++ b/src/libraries/CtxLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEulerSwap} from "../interfaces/IEulerSwap.sol"; +diff --git a/src/libraries/CurveLib.sol b/src/libraries/CurveLib.sol +index 79236aa..a407608 100644 +--- a/src/libraries/CurveLib.sol ++++ b/src/libraries/CurveLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: BUSL-1.1 + pragma solidity ^0.8.27; + + import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +diff --git a/src/libraries/FundsLib.sol b/src/libraries/FundsLib.sol +index 4fce59b..ebc07d0 100644 +--- a/src/libraries/FundsLib.sol ++++ b/src/libraries/FundsLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; +diff --git a/src/libraries/QuoteLib.sol b/src/libraries/QuoteLib.sol +index 3fc582a..84ff826 100644 +--- a/src/libraries/QuoteLib.sol ++++ b/src/libraries/QuoteLib.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +diff --git a/src/utils/ProtocolFee.sol b/src/utils/ProtocolFee.sol +index c933fbb..1befa2e 100644 +--- a/src/utils/ProtocolFee.sol ++++ b/src/utils/ProtocolFee.sol +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: UNLICENSED ++// SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.27; + + import {Owned} from "solmate/src/auth/Owned.sol"; +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (eulOFTAdapter): + +Adapter files blob-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) (evc): + +Descendant of the baseline and the last commit ever to touch src/ on origin/master — the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers — proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding). + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultImplementation + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`abfbfc9f`](https://github.com/euler-xyz/euler-price-oracle/tree/abfbfc9fa3a7c74024df3a75be48282fce5e15ae)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (rEUL): + +Component files byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (swapVerifier): + +Descendant of the baseline by 3 days (the merge adding the Enigma report PDF). src/Swaps delta is 100% non-semantic forge-fmt re-wrapping. This IS the Enigma-fixes-included state as deployed on 13 chains. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +index b70618d3..d210ab47 100644 +--- a/src/Swaps/MigrationHelper.sol ++++ b/src/Swaps/MigrationHelper.sol +@@ -95,10 +95,7 @@ contract MigrationHelper is EVCUtil { + /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. + /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying + /// the user's permit can only ever drain their own balance. +- function transferBalanceFromSender(address token, uint256 maxAmount, address to) +- external +- returns (uint256 amount) +- { ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) external returns (uint256 amount) { + amount = IERC20(token).balanceOf(_msgSender()); + if (amount > maxAmount) amount = maxAmount; + // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index 23a3c2fd..ec881e76 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -69,7 +69,8 @@ contract SwapVerifier is MigrationHelper { + /// @param receiver The address to transfer the asset to + /// @param amountMin The minimum amount of the asset that must be available before transfer + /// @param deadline A timestamp after which the transfer will revert +- /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if the minimum is met ++ /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if ++ /// the minimum is met + function verifyAmountMinAndTransfer(address asset, address receiver, uint256 amountMin, uint256 deadline) external { + if (deadline < block.timestamp) revert SwapVerifier_pastDeadline(); +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/999.md b/verify/999.md new file mode 100644 index 0000000..13e5392 --- /dev/null +++ b/verify/999.md @@ -0,0 +1,830 @@ +# HyperEVM — Deployed Code Verification + +Chain ID: 999 · Bytecode-proven: **18/18** + +Verification = on-chain runtime bytecode ≡ compile(repo@commit, profile), metadata stripped, immutables masked, embedded child-metadata digests zeroed. The block explorer is never in the trust path. Each proven pin is then diffed against its component's audited baseline — the fixes-included state of the component's most recent audit — so every deployed source delta beyond audited code is shown below as a real diff. Re-run: see the repository README. + +## ⚠️ Requires attention + +- **eulerSwapV2ProtocolFeeConfig** — post-audit functionality change ([diff below](#component-euler-swap-v2)): + > **Assessment** + > The deployed V2 release (tag eulerswap-2.0) post-dates the September 2025 Cantina review baseline. Within that delta, protocol-fee handling was redesigned: the reviewed model (fee parameters fixed into each pool at install, 10–25% bounds, permissionless enablement after one year) was replaced by the EulerSwapProtocolFeeConfig singleton, which pools query live on every swap. The fee-config admin can set a default fee and per-pool overrides taking effect immediately, up to MAX_PROTOCOL_FEE = 15% of the LP fee amount (lower than the previously reviewed 25% maximum); zero is allowed. Pre-release hardening is included: the admin and fee recipients may not be known EVC sub-accounts, and configuration events are emitted. Curve and quote math are unchanged by this mechanism. It post-dates the September 2025 review and is not yet listed in the audit registry. + +## Core lending protocol + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| balanceTracker | [`0x05d14f4e…`](https://hyperevmscan.io/address/0x05d14f4eDFA7Cbfb90711C2EC5505bcbd49b9cD2) | [`reward-streams@9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) | ✅ `47294620` | +55/−13 vs baseline | claim return values + isRewardEnabled view | +| EUL | [`0x3A41f426…`](https://hyperevmscan.io/address/0x3A41f426E55ECdE4BC734fA79ccE991b94aFf711) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `0b021e3f` | ≡ baseline | — | +| eulOFTAdapter | [`0x976666e0…`](https://hyperevmscan.io/address/0x976666e0ae74A8A4059cF1acf706891aDE98C3d1) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `1036d1c0` | ≡ baseline | — | +| eVaultFactory | [`0xcF555258…`](https://hyperevmscan.io/address/0xcF5552580fD364cdBBFcB5Ae345f75674c59273A) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `3971bde2` | +1/−1 vs baseline | one fee-share default parameter | +| eVaultImplementation | [`0x05de079A…`](https://hyperevmscan.io/address/0x05de079A28386135E048369cdf0Bc4D326d5EBDF) | [`euler-vault-kit@422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) | ✅ `8c001272` | +15/−8 vs baseline | setLTV patch (audited ×2) + param | +| evc | [`0xceAA7cdC…`](https://hyperevmscan.io/address/0xceAA7cdCD7dDBee8601127a9Abb17A974d613db4) | [`ethereum-vault-connector@a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) | ✅ `b12f6d72` | +58/−11 vs baseline | EVCUtil helper + signer-exclusion hardening | +| oracleRouterFactory | [`0x1CefA54e…`](https://hyperevmscan.io/address/0x1CefA54ebBCb6c9Aa7347196B03364aFe9A89f7e) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `d7881094` | +10/−1 vs baseline | EVC constructor pass-through | +| protocolConfig | [`0x43144f09…`](https://hyperevmscan.io/address/0x43144f09896F8759DE2ec6D777391B9F05A51128) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `844a4ed8` | +1/−1 vs baseline | one fee-share default parameter | +| rEUL | [`0x14DCA654…`](https://hyperevmscan.io/address/0x14DCA6543Ef03b932cBD801FBfd70e42a9b6122b) | [`evk-periphery@392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) | ✅ `ea6d1628` | ≡ baseline | — | +| sequenceRegistry | [`0x47618E4C…`](https://hyperevmscan.io/address/0x47618E4CBDcFBf5f21D6594A7e3a4f4683719994) | [`euler-vault-kit@9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) | ✅ `83359e00` | +1/−1 vs baseline | one fee-share default parameter | +| swapVerifier | [`0x11F6386A…`](https://hyperevmscan.io/address/0x11F6386A84b04E83Ecd647Cb1f492a66B7A3Be33) | [`evk-periphery@edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) | ✅ `2fc2cdd1` | +3/−5 vs baseline | formatting only | + +## Euler Earn + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerEarnFactory | [`0x587DD828…`](https://hyperevmscan.io/address/0x587DD8285c01526769aB4803e4F02433ddbBc00E) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `c9ee150e` | +18/−18 vs baseline | import-path style only | +| eulerEarnPublicAllocator | [`0xc00ae658…`](https://hyperevmscan.io/address/0xc00ae658ce425Bb668A5Ed96c8ECa9C988706939) | [`euler-earn@b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) | ✅ `a6bee3db` | +18/−18 vs baseline | import-path style only | + +## EulerSwap + +| Contract | Address | Source | Bytecode | vs audited baseline | What changed | +|----------|---------|--------|----------|---------------------|--------------| +| eulerSwapV2Factory | [`0xFbF2a49C…`](https://hyperevmscan.io/address/0xFbF2a49CB0cc50F4ccd4eAc826eF1A76D99D29Eb) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `4bdd5d47` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Implementation | [`0xC00F0B7d…`](https://hyperevmscan.io/address/0xC00F0B7d7B4F7cA3d3f79f3892069f41C142dB84) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `408124d9` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Periphery | [`0x61aFC386…`](https://hyperevmscan.io/address/0x61aFC386b47a11F8721b67Eb1607cFBd9ccE48B1) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `f98bd760` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2ProtocolFeeConfig | [`0x434b1072…`](https://hyperevmscan.io/address/0x434b1072d96ea24967CDe289D3d4d81d2BAD4F30) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `83e2e2c4` | +444/−267 vs baseline | fee-config redesign + code-size refactor | +| eulerSwapV2Registry | [`0x7E1Efb6A…`](https://hyperevmscan.io/address/0x7E1Efb6A2009A1FDaDee1c5d6615260AD70c14Fb) | [`euler-swap@81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) | ✅ `42c58b74` | +444/−267 vs baseline | fee-config redesign + code-size refactor | + + +## EVault modules (unpacked from the implementation) + +| Module | Address | Bytecode | Embedded-immutable cross-check | +|--------|---------|----------|-------------------------------| +| Initialize | `0x0BB7341FA538569057265d344946713C3D42A158` | ✅ | ✅ | +| Token | `0x86D5f2Eea2dE26A1a3D25343deCe67e623A1785B` | ✅ | ✅ | +| Vault | `0xEb8588602548c7a84bcA8B4ca26eCdc61D0Cf37d` | ✅ | ✅ | +| Borrowing | `0x5aC2F803D393bc76704F431A199a027e9B70297B` | ✅ | ✅ | +| Liquidation | `0xa22748af8a4e976eE1e0e39dCDc17Ee0f376597D` | ✅ | ✅ | +| RiskManager | `0xeA466813DBA6448413002A3956Aa56F49E2f1359` | ✅ | ✅ | +| BalanceForwarder | `0xf923C9E785eD033C1CCB0E1B55f86E1Ab2a2E2cA` | ✅ | ✅ | +| Governance | `0x3634B9d047Dfd076170AA3539F9d184493CD79Ca` | ✅ | ✅ | + +## EulerSwap V2 management implementation (unpacked from the implementation) + +EulerSwap delegatecalls management functions into a separate contract whose address is the public immutable `managementImpl`; it is verified from the same euler-swap pin. + +| Contract | Address | Bytecode | Embedded-immutable cross-check | +|----------|---------|----------|-------------------------------| +| EulerSwapManagement | `0xc1f9fFaFe2e63B0eD6D5849753775535094c9066` | ✅ | ✅ | + +## Audited baselines and deployed deltas + +One baseline per component: the fixes-included state of its most recent audit. Empty deltas mean the deployed source equals the audited code on the component paths; every non-empty delta is shown as the exact diff. + +### EUL-bridged — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin — not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) — the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding — no behavior change to this contract._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (EUL): + +Carries the Paladin-audited source revision (natspec blob) — byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### euler-earn — baseline `8c768bd8` ([Pashov Audit Group (`pashov-euler-earn-2025`)](https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf)) + +_Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa — max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by ±18 lines of import-path cosmetics only._ + +Deployed pin [`b2fd6e69`](https://github.com/euler-xyz/euler-earn/tree/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345) (eulerEarnFactory, eulerEarnPublicAllocator): + +±18 lines vs baseline, import-path cosmetics only (no code change). + +```diff +diff --git a/src/EulerEarn.sol b/src/EulerEarn.sol +index 4635a89..27c1873 100644 +--- a/src/EulerEarn.sol ++++ b/src/EulerEarn.sol +@@ -17,12 +17,12 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + import {SafeERC20Permit2Lib} from "./libraries/SafeERC20Permit2Lib.sol"; + import {UtilsLib, WAD} from "./libraries/UtilsLib.sol"; +-import {SafeCast} from "../lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; +-import {IERC20Metadata} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol"; ++import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +-import {Context} from "../lib/openzeppelin-contracts/contracts/utils/Context.sol"; +-import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +-import {Ownable2Step, Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"; ++import {Context} from "openzeppelin-contracts/utils/Context.sol"; ++import {ReentrancyGuard} from "openzeppelin-contracts/utils/ReentrancyGuard.sol"; ++import {Ownable2Step, Ownable} from "openzeppelin-contracts/access/Ownable2Step.sol"; + import { + IERC20, + IERC4626, +@@ -30,8 +30,8 @@ import { + ERC4626, + Math, + SafeERC20 +-} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarn + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/EulerEarnFactory.sol b/src/EulerEarnFactory.sol +index 758185e..e7fd335 100644 +--- a/src/EulerEarnFactory.sol ++++ b/src/EulerEarnFactory.sol +@@ -10,8 +10,8 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + + import {EulerEarn} from "./EulerEarn.sol"; + +-import {Ownable, Context} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {Ownable, Context} from "openzeppelin-contracts/access/Ownable.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title EulerEarnFactory + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/PublicAllocator.sol b/src/PublicAllocator.sol +index f71306c..9527976 100644 +--- a/src/PublicAllocator.sol ++++ b/src/PublicAllocator.sol +@@ -14,8 +14,8 @@ import {IEulerEarn, MarketAllocation} from "./interfaces/IEulerEarn.sol"; + import {ErrorsLib} from "./libraries/ErrorsLib.sol"; + import {EventsLib} from "./libraries/EventsLib.sol"; + +-import {IERC4626} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {EVCUtil} from "../lib/ethereum-vault-connector/src/utils/EVCUtil.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; + + /// @title PublicAllocator + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/interfaces/IEulerEarn.sol b/src/interfaces/IEulerEarn.sol +index 27334f2..ed18e7e 100644 +--- a/src/interfaces/IEulerEarn.sol ++++ b/src/interfaces/IEulerEarn.sol +@@ -3,8 +3,8 @@ pragma solidity >=0.5.0; + + import {IEulerEarnFactory} from "./IEulerEarnFactory.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +-import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; ++import {IERC20Permit} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Permit.sol"; + + import {MarketConfig, PendingUint136, PendingAddress} from "../libraries/PendingLib.sol"; + +diff --git a/src/interfaces/IPublicAllocator.sol b/src/interfaces/IPublicAllocator.sol +index b222ce3..4a9067b 100644 +--- a/src/interfaces/IPublicAllocator.sol ++++ b/src/interfaces/IPublicAllocator.sol +@@ -3,7 +3,7 @@ pragma solidity >=0.5.0; + + import {MarketAllocation} from "./IEulerEarn.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @dev Max settable flow cap, such that caps can always be stored on 128 bits. + /// @dev The actual max possible flow cap is type(uint128).max-1. +diff --git a/src/libraries/ErrorsLib.sol b/src/libraries/ErrorsLib.sol +index 300bb22..da0feca 100644 +--- a/src/libraries/ErrorsLib.sol ++++ b/src/libraries/ErrorsLib.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + pragma solidity ^0.8.0; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + /// @title ErrorsLib + /// @author Forked with gratitude from Morpho Labs. Inspired by Silo Labs. +diff --git a/src/libraries/EventsLib.sol b/src/libraries/EventsLib.sol +index f9dc967..862b344 100644 +--- a/src/libraries/EventsLib.sol ++++ b/src/libraries/EventsLib.sol +@@ -3,7 +3,7 @@ pragma solidity ^0.8.0; + + import {FlowCapsConfig} from "../interfaces/IPublicAllocator.sol"; + +-import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; ++import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol"; + + import {PendingAddress} from "./PendingLib.sol"; + +diff --git a/src/libraries/SafeERC20Permit2Lib.sol b/src/libraries/SafeERC20Permit2Lib.sol +index 59603da..0e633eb 100644 +--- a/src/libraries/SafeERC20Permit2Lib.sol ++++ b/src/libraries/SafeERC20Permit2Lib.sol +@@ -3,8 +3,8 @@ + pragma solidity ^0.8.0; + + import {IAllowanceTransfer} from "../interfaces/IAllowanceTransfer.sol"; +-import {IERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +-import {SafeERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; ++import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; ++import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + + /// @title SafeERC20Permit2Lib Library + /// @custom:security-contact security@euler.xyz +``` + +### euler-swap-v2 — baseline `22bb23aa` ([Cantina (`cantina-euler-swap-v2-2025-09`)](https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf)) + +_Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit._ + +Deployed pin [`81cf6dc9`](https://github.com/euler-xyz/euler-swap/tree/81cf6dc988468fd56f690e6bc0e338a5be02d034) (eulerSwapV2Factory, eulerSwapV2Implementation, eulerSwapV2Periphery, eulerSwapV2ProtocolFeeConfig, eulerSwapV2Registry): + +Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/−267 in src/): (1) the protocol-fee mechanism replacement — new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository. + + > **Assessment** · severity: **info** + > Beyond the fee mechanism, the post-baseline delta is an EIP-170 code-size refactor that moved management functions into EulerSwapManagement — a separate delegatecall implementation whose address is a public immutable of EulerSwap. Its deployed bytecode is verified in this report from the same euler-swap pin, with the getter value cross-checked against the implementation’s embedded immutable words. The delta also includes ZeroShares handling for EulerEarn-style vaults and pre-release hardening (pool kept locked during activate), landed at the eulerswap-2.0 release merge. + +Delta: 14 file(s), +444/−267 — too large to embed; per-file: +``` +28 145 src/EulerSwap.sol +32 0 src/EulerSwapBase.sol +13 16 src/EulerSwapFactory.sol +166 0 src/EulerSwapManagement.sol +118 0 src/EulerSwapProtocolFeeConfig.sol +2 0 src/EulerSwapRegistry.sol +16 24 src/UniswapHook.sol +5 2 src/interfaces/IEulerSwap.sol +4 0 src/interfaces/IEulerSwapCallee.sol +29 0 src/interfaces/IEulerSwapProtocolFeeConfig.sol +4 3 src/libraries/CtxLib.sol +8 5 src/libraries/FundsLib.sol +19 7 src/libraries/SwapLib.sol +0 65 src/utils/ProtocolFee.sol +``` +_Reproduce: `git diff 22bb23aa456a 81cf6dc98846 -- src/` in euler-xyz/euler-swap._ + +### eulOFTAdapter — baseline `e3699ffb` ([Paladin Blockchain Security (`paladin-layerzero-adapters-2025`)](https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf)) + +_Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (eulOFTAdapter): + +Adapter files blob-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### evc — baseline `084b3228` ([yAudit (`yaudit-evc-2024-comp-fixes`)](https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)) + +_Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) — no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10→100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon — it covers that pin's delta rather than anchoring the component._ + +Deployed pin [`a7d3c29e`](https://github.com/euler-xyz/ethereum-vault-connector/tree/a7d3c29ef7e4964736e47675e0588630d6afbfd7) (evc): + +Descendant of the baseline and the last commit ever to touch src/ on origin/master — the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers — proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding). + + > **Assessment** · severity: **low** + > The multichain pin (and Polygon’s set-size descendant) includes PRs #178/#179: isSignerValid excludes the EIP-7587 precompile range and the 0x42 predeploy address space from acting as message signers. Proactive, restrictive-only hardening (five lines) added ahead of the Nov-2024 multichain deployment; it maps to no registered audit finding. + +```diff +diff --git a/src/EthereumVaultConnector.sol b/src/EthereumVaultConnector.sol +index 95009da..e6bc820 100644 +--- a/src/EthereumVaultConnector.sol ++++ b/src/EthereumVaultConnector.sol +@@ -27,6 +27,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + string public constant name = "Ethereum Vault Connector"; + + uint160 internal constant ACCOUNT_ID_OFFSET = 8; ++ address internal constant EIP_7587_PRECOMPILES = 0x0000000000000000000000000000000000000100; ++ address internal constant COMMON_PREDEPLOYS = 0x4200000000000000000000000000000000000000; + bytes32 internal constant HASHED_NAME = keccak256(bytes(name)); + + bytes32 internal constant TYPE_HASH = +@@ -1045,7 +1047,8 @@ contract EthereumVaultConnector is Events, Errors, TransientStorage, IEVC { + function isSignerValid(address signer) internal pure virtual returns (bool) { + // not valid if the signer address falls into any of the precompiles/predeploys + // addresses space (depends on the chain ID). +- return !haveCommonOwnerInternal(signer, address(0)); ++ return !haveCommonOwnerInternal(signer, address(0)) && !haveCommonOwnerInternal(signer, EIP_7587_PRECOMPILES) ++ && !haveCommonOwnerInternal(signer, COMMON_PREDEPLOYS); + } + + /// @notice Computes the permit hash for a given set of parameters. +diff --git a/src/utils/EVCUtil.sol b/src/utils/EVCUtil.sol +index cf57295..dc4e432 100644 +--- a/src/utils/EVCUtil.sol ++++ b/src/utils/EVCUtil.sol +@@ -29,7 +29,7 @@ abstract contract EVCUtil { + + /// @notice Returns the address of the Ethereum Vault Connector (EVC) used by this contract. + /// @return The address of the EVC contract. +- function EVC() external view returns (address) { ++ function EVC() external view virtual returns (address) { + return address(evc); + } + +@@ -49,6 +49,18 @@ abstract contract EVCUtil { + _; + } + ++ /// @notice Ensures a standard authentication path on the EVC allowing the account owner or any of its EVC accounts. ++ /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. ++ /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. ++ /// @dev This modifier must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This modifier must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ modifier onlyEVCAccount() virtual { ++ _authenticateCallerWithStandardContextState(false); ++ _; ++ } ++ + /// @notice Ensures a standard authentication path on the EVC. + /// @dev This modifier checks if the caller is the EVC and if so, verifies the execution context. + /// It reverts if the operator is authenticated, control collateral is in progress, or checks are in progress. +@@ -59,7 +71,7 @@ abstract contract EVCUtil { + /// @dev This modifier can be used on access controlled functions to prevent non-standard authentication paths on + /// the EVC. + modifier onlyEVCAccountOwner() virtual { +- _onlyEVCAccountOwner(); ++ _authenticateCallerWithStandardContextState(true); + _; + } + +@@ -121,6 +133,29 @@ abstract contract EVCUtil { + return sender; + } + ++ /// @notice Retrieves the message sender, ensuring it's any EVC account meaning that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccount() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(false); ++ } ++ ++ /// @notice Retrieves the message sender, ensuring it's the EVC account owner and that the execution context is in a ++ /// standard state (not operator authenticated, not control collateral in progress, not checks in progress). ++ /// @dev It assumes that if the caller is not the EVC, the caller is the account owner. ++ /// @dev This function must not be used on functions utilized by liquidation flows, i.e. transfer or withdraw. ++ /// @dev This function must not be used on checkAccountStatus and checkVaultStatus functions. ++ /// @dev This function can be used on access controlled functions to prevent non-standard authentication paths on ++ /// the EVC. ++ /// @return The address of the message sender. ++ function _msgSenderOnlyEVCAccountOwner() internal view returns (address) { ++ return _authenticateCallerWithStandardContextState(true); ++ } ++ + /// @notice Calls the current external function through the EVC. + /// @dev This function is used to route the current call through the EVC if it's not already coming from the EVC. It + /// makes the EVC set the execution context and call back this contract with unchanged calldata. msg.sender is used +@@ -159,12 +194,14 @@ abstract contract EVCUtil { + } + } + +- /// @notice Ensures that the function is called only by the EVC account owner ++ /// @notice Ensures that the function is called only by the EVC account owner or any of its EVC accounts + /// @dev This function checks if the caller is the EVC and if so, verifies that the execution context is not in a +- /// special state (operator authenticated, collateral control in progress, or checks in progress). If the owner was +- /// already registered on the EVC, it verifies that the onBehalfOfAccount is the owner. +- /// @dev Reverts if the caller is not the EVC or if the execution context is in a special state. +- function _onlyEVCAccountOwner() internal view { ++ /// special state (operator authenticated, collateral control in progress, or checks in progress). If ++ /// onlyAccountOwner is true and the owner was already registered on the EVC, it verifies that the onBehalfOfAccount ++ /// is the owner. If onlyAccountOwner is false, it allows any EVC account of the owner to call the function. ++ /// @param onlyAccountOwner If true, only allows the account owner; if false, allows any EVC account of the owner ++ /// @return The address of the message sender. ++ function _authenticateCallerWithStandardContextState(bool onlyAccountOwner) internal view returns (address) { + if (msg.sender == address(evc)) { + EC ec = EC.wrap(evc.getRawExecutionContext()); + +@@ -173,11 +210,18 @@ abstract contract EVCUtil { + } + + address onBehalfOfAccount = ec.getOnBehalfOfAccount(); +- address owner = evc.getAccountOwner(onBehalfOfAccount); + +- if (owner != address(0) && owner != onBehalfOfAccount) { +- revert NotAuthorized(); ++ if (onlyAccountOwner) { ++ address owner = evc.getAccountOwner(onBehalfOfAccount); ++ ++ if (owner != address(0) && owner != onBehalfOfAccount) { ++ revert NotAuthorized(); ++ } + } ++ ++ return onBehalfOfAccount; + } ++ ++ return msg.sender; + } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`422bf244`](https://github.com/euler-xyz/euler-vault-kit/tree/422bf2447047d32aa9f4e5bab4be16ab3ea67ec2) (eVaultImplementation + the 8 EVault modules): + +The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) — reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv — plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree. + +```diff +diff --git a/src/EVault/modules/Governance.sol b/src/EVault/modules/Governance.sol +index 5c728ed..08c5c96 100644 +--- a/src/EVault/modules/Governance.sol ++++ b/src/EVault/modules/Governance.sol +@@ -290,7 +290,7 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + ConfigAmount newBorrowLTV = borrowLTV.toConfigAmount(); + ConfigAmount newLiquidationLTV = liquidationLTV.toConfigAmount(); + +- // The borrow LTV must be lower than or equal to the the converged liquidation LTV ++ // The borrow LTV must be lower than or equal to the converged liquidation LTV + if (newBorrowLTV > newLiquidationLTV) revert E_LTVBorrow(); + + LTVConfig memory currentLTV = vaultStorage.ltvLookup[collateral]; +@@ -304,12 +304,6 @@ abstract contract GovernanceModule is IGovernance, BalanceUtils, BorrowUtils, LT + + if (!currentLTV.isRecognizedCollateral()) vaultStorage.ltvList.push(collateral); + +- if (!newLiquidationLTV.isZero()) { +- // Ensure that this collateral can be priced by the configured oracle +- (, IPriceOracle _oracle, address _unitOfAccount) = ProxyUtils.metadata(); +- _oracle.getQuote(1e18, collateral, _unitOfAccount); +- } +- + emit GovSetLTV( + collateral, + newLTV.borrowLTV.toUint16(), +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +diff --git a/src/Synths/ESynth.sol b/src/Synths/ESynth.sol +index cece73c..e059d29 100644 +--- a/src/Synths/ESynth.sol ++++ b/src/Synths/ESynth.sol +@@ -177,4 +177,17 @@ contract ESynth is ERC20EVCCompatible, Ownable { + } + return total; + } ++ ++ /// @dev Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be ++ /// called by the current owner. ++ /// NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is ++ /// only available to the owner. ++ function renounceOwnership() public virtual override onlyEVCAccountOwner { ++ super.renounceOwnership(); ++ } ++ ++ /// @dev Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner. ++ function transferOwnership(address newOwner) public virtual override onlyEVCAccountOwner { ++ super.transferOwnership(newOwner); ++ } + } +``` + +### evk — baseline `1dad88bd` ([yAudit (`yaudit-evk-2024-comp-fixes`)](https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf)) + +_Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified — no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date — its reviewed revision (2024-05-20) predates these fixes._ + +Deployed pin [`9e3c760e`](https://github.com/euler-xyz/euler-vault-kit/tree/9e3c760e051f5d769f7c6edb9be30198a55117d4) (eVaultFactory, protocolConfig, sequenceRegistry + the 8 EVault modules): + +Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4→0.5e4, PR #264) — the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state. + +```diff +diff --git a/src/ProtocolConfig/ProtocolConfig.sol b/src/ProtocolConfig/ProtocolConfig.sol +index c0f2ce7..71fd403 100644 +--- a/src/ProtocolConfig/ProtocolConfig.sol ++++ b/src/ProtocolConfig/ProtocolConfig.sol +@@ -87,7 +87,7 @@ contract ProtocolConfig is IProtocolConfig { + + minInterestFee = 0.1e4; + maxInterestFee = 1e4; +- protocolFeeShare = 0.1e4; ++ protocolFeeShare = 0.5e4; + } + + /// @inheritdoc IProtocolConfig +``` + +### oracleRouterFactory — baseline `11637ffe` ([yAudit (Electisec) (`yaudit-evk-periphery-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf)) + +_yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself — baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier)._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (oracleRouterFactory): + +Identical factory delta to the mainnet pin (same blobs). + + > **Assessment** · severity: **low** + > All four deployed pins share one factory-shell delta vs the audited baseline: the EVC address threaded through the factory constructor into each deployed EulerRouter (+10/−1). The router-side EVC integration this mirrors was audited (Cantina finding 443 fix, approved by the yAudit fixes review); the factory shell itself was not re-reviewed after June 2024. The embedded EulerRouter source has been frozen since Aug 2024 and is byte-identical across all deployed gitlinks modulo import-path cosmetics. + +```diff +diff --git a/src/OracleFactory/EulerRouterFactory.sol b/src/EulerRouterFactory/EulerRouterFactory.sol +similarity index 72% +rename from src/OracleFactory/EulerRouterFactory.sol +rename to src/EulerRouterFactory/EulerRouterFactory.sol +index 10a48c6c..e33fb70e 100644 +--- a/src/OracleFactory/EulerRouterFactory.sol ++++ b/src/EulerRouterFactory/EulerRouterFactory.sol +@@ -11,11 +11,20 @@ import {IEulerRouterFactory} from "./interfaces/IEulerRouterFactory.sol"; + /// @author Euler Labs (https://www.eulerlabs.com/) + /// @notice A minimal factory for EulerRouter. + contract EulerRouterFactory is BaseFactory, IEulerRouterFactory { ++ address public immutable EVC; ++ ++ /// @notice Constructor for the EulerRouterFactory contract. ++ /// @param _evc The address of the Ethereum Vault Connector (EVC). ++ constructor(address _evc) { ++ require(_evc != address(0), "Invalid EVC address"); ++ EVC = _evc; ++ } ++ + /// @notice Deploys a new EulerRouter. + /// @param governor The governor of the router. + /// @return The deployment address. + function deploy(address governor) external returns (address) { +- address router = address(new EulerRouter(governor)); ++ address router = address(new EulerRouter(EVC, governor)); + deploymentInfo[router] = DeploymentInfo(msg.sender, uint96(block.timestamp)); + deployments.push(address(router)); + emit ContractDeployed(router, msg.sender, block.timestamp); +diff --git a/src/OracleFactory/interfaces/IEulerRouterFactory.sol b/src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +similarity index 100% +rename from src/OracleFactory/interfaces/IEulerRouterFactory.sol +rename to src/EulerRouterFactory/interfaces/IEulerRouterFactory.sol +``` + +Embedded `euler-price-oracle` (submodule @ [`abfbfc9f`](https://github.com/euler-xyz/euler-price-oracle/tree/abfbfc9fa3a7c74024df3a75be48282fce5e15ae)) vs its own baseline `47296ad7` ([yAudit (`yaudit-oracle-2024-comp-fixes`)](https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf)): +4/−4 + +```diff +diff --git a/src/EulerRouter.sol b/src/EulerRouter.sol +index 1d7b349..dd062c7 100644 +--- a/src/EulerRouter.sol ++++ b/src/EulerRouter.sol +@@ -2,9 +2,9 @@ + pragma solidity ^0.8.0; + + import {IERC4626} from "forge-std/interfaces/IERC4626.sol"; +-import {IPriceOracle} from "src/interfaces/IPriceOracle.sol"; +-import {Errors} from "src/lib/Errors.sol"; +-import {Governable} from "src/lib/Governable.sol"; ++import {IPriceOracle} from "./interfaces/IPriceOracle.sol"; ++import {Errors} from "./lib/Errors.sol"; ++import {Governable} from "./lib/Governable.sol"; + + /// @title EulerRouter + /// @custom:security-contact security@euler.xyz +diff --git a/src/lib/Governable.sol b/src/lib/Governable.sol +index fc636f5..57b8159 100644 +--- a/src/lib/Governable.sol ++++ b/src/lib/Governable.sol +@@ -2,7 +2,7 @@ + pragma solidity ^0.8.0; + + import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +-import {Errors} from "src/lib/Errors.sol"; ++import {Errors} from "./Errors.sol"; + + /// @title Governable + /// @custom:security-contact security@euler.xyz +``` + +### rEUL — baseline `20df7d77` ([CD Security (`cdsecurity-erc20wrapperlocked-2024`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf)) + +_CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) — making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip)._ + +Deployed pin [`392c7bd0`](https://github.com/euler-xyz/evk-periphery/tree/392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8) (rEUL): + +Component files byte-identical to the baseline. + +**Deployed source is identical to the audited baseline** on the component paths. + +### reward-streams — baseline `d124216a` ([Cantina (`cantina-reward-streams-2024`)](https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf)) + +_Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1–#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a — every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review._ + +Deployed pin [`9eb7b8a7`](https://github.com/euler-xyz/reward-streams/tree/9eb7b8a7fa31c275d688063c4abd07165b50b89f) (balanceTracker): + +Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view — interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil. + + > **Assessment** · severity: **low** + > The deployed pin post-dates the audit-verified baseline by one source change: PR #26, which made enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, and added the isRewardEnabled view. Interface/return plumbing with no accounting change; it post-dates every registered audit’s reviewed revision. The pin also bumps the EVC submodule to v1.0.0, the Cantina-fixed EVC release. + +```diff +diff --git a/src/BaseRewardStreams.sol b/src/BaseRewardStreams.sol +index 8908141..d3caec1 100644 +--- a/src/BaseRewardStreams.sol ++++ b/src/BaseRewardStreams.sol +@@ -204,7 +204,12 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to receive the spillover reward tokens. +- function updateReward(address rewarded, address reward, address recipient) public virtual override { ++ /// @return The amount of the spillover reward tokens claimed. ++ function updateReward( ++ address rewarded, ++ address reward, ++ address recipient ++ ) public virtual override returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -221,8 +226,10 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ); + + if (recipient != address(0)) { +- claim(address(0), rewarded, reward, recipient); ++ return claim(address(0), rewarded, reward, recipient); + } ++ ++ return 0; + } + + /// @notice Claims earned reward. +@@ -231,12 +238,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param reward The address of the reward token. + /// @param recipient The address to receive the claimed reward tokens. + /// @param ignoreRecentReward Whether to ignore the most recent reward and not update the accumulator. ++ /// @return The amount of the claimed reward tokens. + function claimReward( + address rewarded, + address reward, + address recipient, + bool ignoreRecentReward +- ) external virtual override nonReentrant { ++ ) external virtual override nonReentrant returns (uint256) { + address msgSender = _msgSender(); + + // If the account disables the rewards we pass an account balance of zero to not accrue any. +@@ -252,19 +260,21 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + ignoreRecentReward + ); + +- claim(msgSender, rewarded, reward, recipient); ++ return claim(msgSender, rewarded, reward, recipient); + } + + /// @notice Enable reward token. + /// @dev There can be at most MAX_REWARDS_ENABLED rewards enabled for the rewarded token and the account. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. +- function enableReward(address rewarded, address reward) external virtual override { ++ /// @return Whether the reward token was enabled. ++ function enableReward(address rewarded, address reward) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; + SetStorage storage accountEnabledRewards = accountStorage.enabledRewards; ++ bool wasEnabled = accountEnabledRewards.insert(reward); + +- if (accountEnabledRewards.insert(reward)) { ++ if (wasEnabled) { + if (accountEnabledRewards.numElements > MAX_REWARDS_ENABLED) { + revert TooManyRewardsEnabled(); + } +@@ -280,17 +290,25 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardEnabled(msgSender, rewarded, reward); + } ++ ++ return wasEnabled; + } + + /// @notice Disable reward token. + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param forfeitRecentReward Whether to forfeit the recent rewards and not update the accumulator. +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external virtual override { ++ /// @return Whether the reward token was disabled. ++ function disableReward( ++ address rewarded, ++ address reward, ++ bool forfeitRecentReward ++ ) external virtual override returns (bool) { + address msgSender = _msgSender(); + AccountStorage storage accountStorage = accounts[msgSender][rewarded]; ++ bool wasDisabled = accountStorage.enabledRewards.remove(reward); + +- if (accountStorage.enabledRewards.remove(reward)) { ++ if (wasDisabled) { + DistributionStorage storage distributionStorage = distributions[rewarded][reward]; + uint256 currentAccountBalance = accountStorage.balance; + +@@ -307,6 +325,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + + emit RewardDisabled(msgSender, rewarded, reward); + } ++ ++ return wasDisabled; + } + + /// @notice Returns the earned reward token amount for a specific account and rewarded token. +@@ -348,6 +368,19 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + return accounts[account][rewarded].enabledRewards.get(); + } + ++ /// @notice Checks if a specific reward token is enabled for an account and rewarded token. ++ /// @param account The address of the account. ++ /// @param rewarded The address of the rewarded token. ++ /// @param reward The address of the reward token to check if enabled. ++ /// @return Whether the reward token is enabled for the account and rewarded token. ++ function isRewardEnabled( ++ address account, ++ address rewarded, ++ address reward ++ ) external view virtual override returns (bool) { ++ return accounts[account][rewarded].enabledRewards.contains(reward); ++ } ++ + /// @notice Returns the rewarded token balance of a specific account. + /// @param account The address of the account. + /// @param rewarded The address of the rewarded token. +@@ -503,7 +536,13 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + /// @param rewarded The address of the rewarded token. + /// @param reward The address of the reward token. + /// @param recipient The address to which the claimed reward will be transferred. +- function claim(address account, address rewarded, address reward, address recipient) internal virtual { ++ /// @return The amount of the claimed reward tokens. ++ function claim( ++ address account, ++ address rewarded, ++ address reward, ++ address recipient ++ ) internal virtual returns (uint256) { + EarnStorage storage accountEarned = accounts[account][rewarded].earned[reward]; + uint128 amount = accountEarned.claimable; + +@@ -522,6 +561,8 @@ abstract contract BaseRewardStreams is IRewardStreams, EVCUtil, ReentrancyGuard + pushToken(IERC20(reward), recipient, amount); + emit RewardClaimed(account, rewarded, reward, amount); + } ++ ++ return amount; + } + + /// @notice Updates the data for a specific account, rewarded token and reward token. +diff --git a/src/interfaces/IRewardStreams.sol b/src/interfaces/IRewardStreams.sol +index 7cae777..0ac3904 100644 +--- a/src/interfaces/IRewardStreams.sol ++++ b/src/interfaces/IRewardStreams.sol +@@ -14,12 +14,13 @@ interface IRewardStreams { + function MAX_DISTRIBUTION_LENGTH() external view returns (uint256); + function MAX_REWARDS_ENABLED() external view returns (uint256); + function registerReward(address rewarded, address reward, uint48 startEpoch, uint128[] calldata rewardAmounts) external; +- function updateReward(address rewarded, address reward, address recipient) external; +- function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external; +- function enableReward(address rewarded, address reward) external; +- function disableReward(address rewarded, address reward, bool forfeitRecentReward) external; ++ function updateReward(address rewarded, address reward, address recipient) external returns (uint256); ++ function claimReward(address rewarded, address reward, address recipient, bool ignoreRecentReward) external returns (uint256); ++ function enableReward(address rewarded, address reward) external returns (bool); ++ function disableReward(address rewarded, address reward, bool forfeitRecentReward) external returns (bool); + function earnedReward(address account, address rewarded, address reward, bool ignoreRecentReward) external view returns (uint256); + function enabledRewards(address account, address rewarded) external view returns (address[] memory); ++ function isRewardEnabled(address account, address rewarded, address reward) external view returns (bool); + function balanceOf(address account, address rewarded) external view returns (uint256); + function rewardAmount(address rewarded, address reward) external view returns (uint256); + function totalRewardedEligible(address rewarded, address reward) external view returns (uint256); +``` + +### swapVerifier — baseline `469d9cfe` ([Enigma Dark (`enigma-dark-swapverifier-update-2026`)](https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf)) + +_Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch._ + +Deployed pin [`edaf96e3`](https://github.com/euler-xyz/evk-periphery/tree/edaf96e32ebe6cb96ae30add934d74fa1d092ff6) (swapVerifier): + +Descendant of the baseline by 3 days (the merge adding the Enigma report PDF). src/Swaps delta is 100% non-semantic forge-fmt re-wrapping. This IS the Enigma-fixes-included state as deployed on 13 chains. + +```diff +diff --git a/src/Swaps/MigrationHelper.sol b/src/Swaps/MigrationHelper.sol +index b70618d3..d210ab47 100644 +--- a/src/Swaps/MigrationHelper.sol ++++ b/src/Swaps/MigrationHelper.sol +@@ -95,10 +95,7 @@ contract MigrationHelper is EVCUtil { + /// Size the signed permit `value` to `maxAmount` so the allowance always covers the capped transfer. + /// @dev As with {transferFromSender}, the source is bound to `_msgSender()`, so a front-runner replaying + /// the user's permit can only ever drain their own balance. +- function transferBalanceFromSender(address token, uint256 maxAmount, address to) +- external +- returns (uint256 amount) +- { ++ function transferBalanceFromSender(address token, uint256 maxAmount, address to) external returns (uint256 amount) { + amount = IERC20(token).balanceOf(_msgSender()); + if (amount > maxAmount) amount = maxAmount; + // Short-circuit a zero pull: nothing to move, and some ERC20s revert on zero-value transfers. +diff --git a/src/Swaps/SwapVerifier.sol b/src/Swaps/SwapVerifier.sol +index 23a3c2fd..ec881e76 100644 +--- a/src/Swaps/SwapVerifier.sol ++++ b/src/Swaps/SwapVerifier.sol +@@ -69,7 +69,8 @@ contract SwapVerifier is MigrationHelper { + /// @param receiver The address to transfer the asset to + /// @param amountMin The minimum amount of the asset that must be available before transfer + /// @param deadline A timestamp after which the transfer will revert +- /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if the minimum is met ++ /// @dev This function checks for slippage and sends all of the contract's balance of the asset to the receiver if ++ /// the minimum is met + function verifyAmountMinAndTransfer(address asset, address receiver, uint256 amountMin, uint256 deadline) external { + if (deadline < block.timestamp) revert SwapVerifier_pastDeadline(); +``` + +_Generated by euler-verifier @ feat/p2-manifests; inputs: verify/manifest.json, verify/audits.json, verify/baselines.json._ diff --git a/verify/README.md b/verify/README.md new file mode 100644 index 0000000..e853ab6 --- /dev/null +++ b/verify/README.md @@ -0,0 +1,25 @@ +# Deployed Code Verification Reports + +Bytecode-level verification of every allowlisted Euler contract: on-chain code is proven equal to a commit-pinned local build (metadata stripped, immutables masked) — the block explorer is never in the trust path — then each deployment is diffed against its component's audited baseline: the fixes-included state of the component's most recent audit. Reports lead with anything requiring attention and show every deployed source delta beyond audited code as a real diff. Reproducible by anyone. + +| Network | Chain ID | Proven | +|---------|----------|--------| +| [Ethereum Mainnet](1.md) | 1 | 20/21 (+1 canonical) | +| [BSC](56.md) | 56 | 21/21 | +| [Unichain](130.md) | 130 | 21/21 | +| [Polygon](137.md) | 137 | 10/10 | +| [Monad](143.md) | 143 | 16/16 | +| [Sonic](146.md) | 146 | 21/21 | +| [TAC](239.md) | 239 | 21/21 | +| [HyperEVM](999.md) | 999 | 18/18 | +| [Swell](1923.md) | 1923 | 21/21 | +| [Morph](2818.md) | 2818 | 18/18 | +| [Base](8453.md) | 8453 | 21/21 | +| [Plasma](9745.md) | 9745 | 21/21 | +| [Arbitrum](42161.md) | 42161 | 21/21 | +| [Avalanche](43114.md) | 43114 | 21/21 | +| [Linea](59144.md) | 59144 | 21/21 | +| [BOB](60808.md) | 60808 | 21/21 | +| [Berachain](80094.md) | 80094 | 21/21 | + +_Inputs: `manifest.json` (declared provenance, SHA-only), `audits.json` (audit registry), `baselines.json` (component baselines with derivations). Regenerated only when a PR changes those inputs or addresses._ diff --git a/verify/audits.json b/verify/audits.json new file mode 100644 index 0000000..9ebe4f3 --- /dev/null +++ b/verify/audits.json @@ -0,0 +1,1785 @@ +[ + { + "id": "yaudit-evc-2023", + "repo": "euler-xyz/ethereum-vault-connector", + "firm": "yAudit", + "date": "2023-12-19", + "commits": { + "reviewed": "962722a69a275c424adaa89e595ca60107376b68", + "final": "c1288b02c2c028378bde4e7bec0dddc288dd51ce" + }, + "scope": [ + "src/interfaces/IERC1271.sol", + "src/interfaces/IEthereumVaultConnector.sol", + "src/interfaces/IVault.sol", + "src/Errors.sol", + "src/EthereumVaultConnector.sol", + "src/Events.sol", + "src/ExecutionContext.sol", + "src/Set.sol", + "src/TransientStorage.sol" + ], + "report": "https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20report%20%28EVC%29.pdf", + "confidence": "high", + "evidence": "p4 Review Summary states verbatim '962722a69...first review and c1288b02...second'; final == tag audit-yAudit-1", + "signed_off": true + }, + { + "id": "certora-evc-2023", + "repo": "euler-xyz/ethereum-vault-connector", + "firm": "Certora", + "date": "2023-12-28", + "commits": { + "reviewed": "41e6ce7813ebf34bf1de46bb637eecbaa5ce1199", + "final": "027be10e1b9e5591cd38be2728530c5fd36dbcf6" + }, + "scope": [ + "src/EthereumVaultConnector.sol" + ], + "report": "https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20Certora%20report.pdf", + "confidence": "low", + "evidence": "No commit stated in PDF (12 pages + 39 links checked); reviewed = nearest master commit to Nov-22-2023 kickoff; final = 027be10 'add certora audit' which added this PDF (Jan-3-2024), near stated final report Dec-28-2023", + "signed_off": true + }, + { + "id": "hunter-evc-2024", + "repo": "euler-xyz/ethereum-vault-connector", + "firm": "Hunter Security", + "date": "2024-01-10", + "commits": { + "reviewed": "89dcbd4d1ad149c060d0365c244746d9b160d5e5", + "final": "5cb1ebf53a1d537db6feabc5acf139891b37a39a" + }, + "scope": [ + "src/Errors.sol", + "src/EthereumVaultConnector.sol", + "src/Events.sol", + "src/ExecutionContext.sol", + "src/Set.sol", + "src/TransientStorage.sol", + "src/interfaces/" + ], + "report": "https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20Hunter%20Security%20report.pdf", + "confidence": "high", + "evidence": "p4 Executive Summary table states 'Commit hash 89dcbd4d...' and 'Resolution 5cb1ebf5...' (== tag audit-Hunter)", + "signed_off": true + }, + { + "id": "trail-of-bits-evc-2024", + "repo": "euler-xyz/ethereum-vault-connector", + "firm": "Trail of Bits", + "date": "2024-01-30", + "commits": { + "reviewed": "8e1b9a7888bb40bdde16659ca47d0c3a7cafbcf6", + "final": "ec26831575513b50273dd3dc04d3d21aca3ec225" + }, + "scope": [ + "src/" + ], + "report": "https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20Trail%20of%20Bits%20report.pdf", + "confidence": "high", + "evidence": "p5 Executive Summary 'at commit 8e1b9a7' (rev-parse); p13 Fix Review PR #81 merge commit == tag audit-ToB", + "signed_off": true + }, + { + "id": "openzeppelin-evc-2024", + "repo": "euler-xyz/ethereum-vault-connector", + "firm": "OpenZeppelin", + "date": "2024-04-16", + "commits": { + "reviewed": "69626eba206ae301b919f021e71b49feaf7ea8f5", + "final": "c30606b44f1d1cabba303dfd13046e5444cab775" + }, + "scope": [ + "src/Errors.sol", + "src/EthereumVaultConnector.sol", + "src/Events.sol", + "src/ExecutionContext.sol", + "src/Set.sol", + "src/TransientStorage.sol", + "src/interfaces/IERC1271.sol", + "src/interfaces/IEthereumVaultConnector.sol", + "src/interfaces/IVault.sol", + "src/utils/EVCUtil.sol" + ], + "report": "https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20OpenZeppelin%20report.pdf", + "confidence": "high", + "evidence": "p4 Scope 'audited...at the 69626eba...commit'; final == tag audit-OZ (ChainSecurity table labels it 'Initial Version, 7 April 2024')", + "signed_off": true + }, + { + "id": "yaudit-evc-2024-combined", + "repo": "euler-xyz/ethereum-vault-connector", + "firm": "yAudit", + "date": "2024-05-05", + "commits": { + "reviewed": "7e1445d45e9189b5132132a6216c146fde9ba794", + "final": "7e1445d45e9189b5132132a6216c146fde9ba794" + }, + "scope": [ + "src/Errors.sol", + "src/EthereumVaultConnector.sol", + "src/Events.sol", + "src/ExecutionContext.sol", + "src/Set.sol", + "src/TransientStorage.sol", + "src/interfaces/IERC1271.sol", + "src/interfaces/IEthereumVaultConnector.sol", + "src/interfaces/IVault.sol", + "src/utils/EVCUtil.sol" + ], + "report": "https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20report%20%28EVC%20%2B%20EVK%20%2B%20Price%20Oracle%29.pdf", + "confidence": "high", + "evidence": "p8 Review Summary states '7e1445d4...for the EVC repo' (== tag audit-yAudit-2). Combined EVC+EVK+EPO review; date normalized to in-doc review-period end 2024-05-05 (shared across the 3 repo copies)", + "signed_off": true + }, + { + "id": "omniscia-evc-2024", + "repo": "euler-xyz/ethereum-vault-connector", + "firm": "Omniscia", + "date": "2024-05-16", + "commits": { + "reviewed": "69626eba206ae301b919f021e71b49feaf7ea8f5", + "final": "c943dcbbb610b285025d5cae5b18e080b429425d" + }, + "scope": [ + "src/Errors.sol", + "src/Events.sol", + "src/utils/EVCUtil.sol", + "src/ExecutionContext.sol", + "src/EthereumVaultConnector.sol", + "src/Set.sol", + "src/TransientStorage.sol" + ], + "report": "https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20Omniscia%20report.pdf", + "confidence": "high", + "evidence": "p10 Target/Scope table 'Commit: 69626eba...', Revisions 69626eba20/577d1991de/c943dcbbb6 (last == tag audit-Omniscia); cover 'May 16, 2024'", + "signed_off": true + }, + { + "id": "spearbit-evc-2024", + "repo": "euler-xyz/ethereum-vault-connector", + "firm": "Spearbit", + "date": "2024-05-17", + "commits": { + "reviewed": "c30606b44f1d1cabba303dfd13046e5444cab775", + "final": "9bc0c17afd6bed51cd9126d9f3b8fc31614d29a9" + }, + "scope": [ + "src/" + ], + "report": "https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20Spearbit%20report.pdf", + "confidence": "high", + "evidence": "p3 Summary 'Commit c30606...cab775' (shared Apr-2024 baseline w/ OZ); 'Fixed in PR 147' == merge of tag audit-Spearbit; cover 'May 17, 2024'", + "signed_off": true + }, + { + "id": "chainsecurity-evc-2024", + "repo": "euler-xyz/ethereum-vault-connector", + "firm": "ChainSecurity", + "date": "2024-06-18", + "commits": { + "reviewed": "c30606b44f1d1cabba303dfd13046e5444cab775", + "final": "9bc0c17afd6bed51cd9126d9f3b8fc31614d29a9" + }, + "scope": [ + "src/ExecutionContext.sol", + "src/EthereumVaultConnector.sol", + "src/TransientStorage.sol", + "src/Errors.sol", + "src/Events.sol", + "src/Set.sol", + "src/utils/EVCUtil.sol" + ], + "report": "https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20ChainSecurity%20report.pdf", + "confidence": "high", + "evidence": "p5 revision table: V1 c30606b4 (7 Apr 2024 Initial), V2 9bc0c17a (22 Apr 2024 After Intermediate Report, == tag audit-ChainSecurity); cover '18 Jun, 2024'", + "signed_off": true + }, + { + "id": "yaudit-evc-2024-comp-fixes", + "repo": "euler-xyz/ethereum-vault-connector", + "firm": "yAudit", + "date": "2024-07-31", + "commits": { + "reviewed": "f791f94e6e790dd82041908983b57412dc04fb84", + "final": "084b32284ba643921f8d21bff3ddaf0c4e08d754" + }, + "scope": [ + "src/" + ], + "report": "https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf", + "confidence": "medium", + "evidence": "PDF scopes companion repo 'evc-cantina-fixes' (no direct main-repo hash). TOC issues cantina-41/102/103/173/196/213/483/516 merged into cantina-fixes = PR#169 = v1.0.0 tag 084b3228; reviewed = cantina-contest baseline. Derived -> medium", + "signed_off": true + }, + { + "id": "cantina-evc-2024", + "repo": "euler-xyz/ethereum-vault-connector", + "firm": "Cantina", + "date": "2024-11-13", + "commits": { + "reviewed": "f791f94e6e790dd82041908983b57412dc04fb84", + "final": "f791f94e6e790dd82041908983b57412dc04fb84" + }, + "scope": [ + "src/" + ], + "report": "https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20Cantina%20Code%20Competition%20report.pdf", + "confidence": "high", + "evidence": "p87 finding hyperlink pins ethereum-vault-connector@f791f94e (== tag cantina-contest); contest 'May 20-Jun 17'; cover 'November 13, 2024'. Multi-repo Euler-v2 competition; EVC scope = whole src/", + "signed_off": true + }, + { + "id": "yaudit-evc-2026-setsize", + "repo": "euler-xyz/ethereum-vault-connector", + "firm": "yAudit", + "date": "2026-05-11", + "commits": { + "reviewed": "dd04b59071525425cab2960ede5d7495847d87ee", + "final": "dd04b59071525425cab2960ede5d7495847d87ee" + }, + "scope": [ + "src/Set.sol", + "src/EthereumVaultConnector.sol" + ], + "report": "https://github.com/euler-xyz/ethereum-vault-connector/blob/b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf/audits/Euler%20yAudit%20report%20%28set%20size%20increase%29.pdf", + "confidence": "high", + "evidence": "p3 'Commit Hash: dd04b590...' verbatim (rev-parse ok); 'Completed 2026-05-11'. WARNING: commit lives only on branch feat/set-max-elements-increase; PDF NOT tracked at pin sha -> report URL 404s", + "signed_off": true + }, + { + "id": "sigma-prime-euler-earn-2025", + "repo": "euler-xyz/euler-earn", + "firm": "Sigma Prime", + "date": "2025-07-01", + "commits": { + "reviewed": "558b15b0444750f742c85feda67ad6b9b851c4db", + "final": "558b15b0444750f742c85feda67ad6b9b851c4db" + }, + "scope": [ + "src/EulerEarn.sol", + "src/EulerEarnFactory.sol", + "src/PublicAllocator.sol", + "src/libraries/*" + ], + "report": "https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Sigma_Prime_EulerEarn_report.pdf", + "confidence": "high", + "evidence": "PDF pages 1-7: 'strictly limited to the following files, assessed at commit 558b15b'. Full hash verified present in euler-earn (origin/master lineage).", + "signed_off": true + }, + { + "id": "certora-euler-earn-2025", + "repo": "euler-xyz/euler-earn", + "firm": "Certora", + "date": "2025-07-15", + "commits": { + "reviewed": "a73c52b718def89ab6c05f2e2fe60841c880639e", + "final": "685ee26bdbc340151070a37087bbd8fa0871a098" + }, + "scope": [ + "src/libraries/**", + "src/EulerEarn.sol", + "src/EulerEarnFactory.sol", + "src/PublicAllocator.sol" + ], + "report": "https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Certora_EulerEarn_report.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6 Project Scope table: 'euler-xyz/euler-earn | a73c52b | 685ee26'; work June 26 - July 15, 2025. Both short hashes resolved in euler-earn.", + "signed_off": true + }, + { + "id": "pashov-euler-earn-2025", + "repo": "euler-xyz/euler-earn", + "firm": "Pashov Audit Group", + "date": "2025-07-30", + "commits": { + "reviewed": "12c0220226cdefc8fee2f229c5e75bd656c7b2b5", + "final": "b95775f4235fe4ea738dde226524d25f317d987c" + }, + "scope": [ + "EulerEarn.sol", + "EulerEarnFactory.sol", + "PublicAllocator.sol", + "ConstantsLib.sol", + "ErrorsLib.sol", + "EventsLib.sol", + "PendingLib.sol", + "SafeERC20Permit2Lib.sol", + "UtilsLib.sol", + "interfaces/" + ], + "report": "https://github.com/euler-xyz/euler-earn/blob/b2fd6e699ee20bcfe7459f375b3cee5d2fa53345/audits/Pashov_Audit_Group_report.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6: 'Review commit hash: 12c0220226cdefc8fee2f229c5e75bd656c7b2b5 (euler-xyz/euler-earn)' / 'Fixes review commit hash: b95775f4235fe4ea738dde226524d25f317d987c'. Both full hashes verified in euler-earn. Scope printed as bare filenames (src/ and src/libraries/ layout).", + "signed_off": true + }, + { + "id": "bailsec-eul-erc20-2025", + "repo": "euler-xyz/euler-governance", + "firm": "BailSec", + "date": "2025-06-01", + "commits": { + "reviewed": "1249ea8be20cd10b795251ba18bc785a26c1361f", + "final": "1249ea8be20cd10b795251ba18bc785a26c1361f" + }, + "scope": [ + "contracts/governance/Eul.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/BailSec%20EUL%20ERC20.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6 Project Details: blob URL github.com/euler-xyz/euler-governance/blob/1249ea8be20cd10b795251ba18bc785a26c1361f/contracts/governance/Eul.sol. Full hash verified present in local euler-governance checkout. NOTE: PDF is filed in evk-periphery/audits but audits euler-governance; report URL points to the PDF's actual location (evk-periphery).", + "signed_off": true + }, + { + "id": "yaudit-oracle-2024-combined", + "repo": "euler-xyz/euler-price-oracle", + "firm": "yAudit", + "date": "2024-05-05", + "commits": { + "reviewed": "416d131f79e66bc54574194ea922bce232ce398c", + "final": "416d131f79e66bc54574194ea922bce232ce398c" + }, + "scope": [ + "src/EulerRouter.sol", + "src/adapter/BaseAdapter.sol", + "src/adapter/CrossAdapter.sol", + "src/adapter/chainlink/AggregatorV3Interface.sol", + "src/adapter/chainlink/ChainlinkOracle.sol", + "src/adapter/chronicle/ChronicleOracle.sol", + "src/adapter/chronicle/IChronicle.sol", + "src/adapter/lido/IStEth.sol", + "src/adapter/lido/LidoOracle.sol", + "src/adapter/maker/IPot.sol", + "src/adapter/maker/SDaiOracle.sol", + "src/adapter/pyth/PythOracle.sol", + "src/adapter/redstone/RedstoneCoreOracle.sol", + "src/adapter/rocketpool/IReth.sol", + "src/adapter/rocketpool/RethOracle.sol", + "src/adapter/uniswap/UniswapV3Oracle.sol", + "src/interfaces/IPriceOracle.sol", + "src/lib/Errors.sol", + "src/lib/Governable.sol", + "src/lib/ScaleUtils.sol" + ], + "report": "https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler_Price_Oracle_yAudit_Report.pdf", + "confidence": "high", + "evidence": "Text 'limited to ...416d131f... for the EPO repo' (combined EVC+EVK+EPO review). Date normalized to in-doc review-period end 2024-05-05 (shared across the 3 repo copies)", + "signed_off": true + }, + { + "id": "omniscia-oracle-2024", + "repo": "euler-xyz/euler-price-oracle", + "firm": "Omniscia", + "date": "2024-05-10", + "commits": { + "reviewed": "c91093256f62ca7d35cc35885d1b8a77d567983d", + "final": "eeb1847df7d9d58029de37225dabf963bf1a65e6" + }, + "scope": [ + "src/adapter/chainlink/AggregatorV3Interface.sol", + "src/adapter/BaseAdapter.sol", + "src/adapter/chainlink/ChainlinkOracle.sol", + "src/adapter/chronicle/ChronicleOracle.sol", + "src/lib/Errors.sol", + "src/EulerRouter.sol", + "src/lib/Governable.sol", + "src/adapter/lido/LidoOracle.sol", + "src/adapter/pyth/PythOracle.sol", + "src/adapter/rocketpool/RethOracle.sol", + "src/adapter/redstone/RedstoneCoreOracle.sol", + "src/adapter/maker/SDaiOracle.sol", + "src/lib/ScaleUtils.sol", + "src/adapter/uniswap/UniswapV3Oracle.sol" + ], + "report": "https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler_Price_Oracle_Omniscia_Report.pdf", + "confidence": "high", + "evidence": "Cover Audit Report Revisions: c91093256f (1 Apr 2024) -> eeb1847df7 (10 May 2024); final == OpenZeppelin-audit tag", + "signed_off": true + }, + { + "id": "chainsecurity-oracle-2024", + "repo": "euler-xyz/euler-price-oracle", + "firm": "ChainSecurity", + "date": "2024-05-15", + "commits": { + "reviewed": "a89b2a4a89d7806702a27592baad03288c74a633", + "final": "e6e87993685ca123e5fa542fb784ba5203824769" + }, + "scope": [ + "src/" + ], + "report": "https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler_Price_Oracle_ChainSecurity_Report.pdf", + "confidence": "high", + "evidence": "Assessment Overview revision table: V1 a89b2a4a (1 May 2024 Initial) -> V2 e6e87993 (15 May 2024 After Intermediate Report). Scope: all files in ./src/ (root ./lib excluded)", + "signed_off": true + }, + { + "id": "openzeppelin-oracle-2024", + "repo": "euler-xyz/euler-price-oracle", + "firm": "OpenZeppelin", + "date": "2024-05-17", + "commits": { + "reviewed": "eeb1847df7d9d58029de37225dabf963bf1a65e6", + "final": "eeb1847df7d9d58029de37225dabf963bf1a65e6" + }, + "scope": [ + "src/EulerRouter.sol", + "src/adapter/BaseAdapter.sol", + "src/adapter/CrossAdapter.sol", + "src/adapter/chainlink/AggregatorV3Interface.sol", + "src/adapter/chainlink/ChainlinkOracle.sol", + "src/adapter/chronicle/ChronicleOracle.sol", + "src/adapter/chronicle/IChronicle.sol", + "src/adapter/lido/IStEth.sol", + "src/adapter/lido/LidoOracle.sol", + "src/adapter/maker/IPot.sol", + "src/adapter/maker/SDaiOracle.sol", + "src/adapter/pyth/PythOracle.sol", + "src/adapter/redstone/RedstoneCoreOracle.sol", + "src/adapter/uniswap/UniswapV3Oracle.sol", + "src/interfaces/IPriceOracle.sol", + "src/lib/Errors.sol", + "src/lib/Governable.sol", + "src/lib/ScaleUtils.sol" + ], + "report": "https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler_Price_Oracle_OpenZeppelin_Report.pdf", + "confidence": "high", + "evidence": "Scope 'at commit eeb1847' == OpenZeppelin-audit tag verbatim; full file tree listed; cover May 17, 2024", + "signed_off": true + }, + { + "id": "spearbit-oracle-2024-draft", + "repo": "euler-xyz/euler-price-oracle", + "firm": "Spearbit", + "date": "2024-05-20", + "commits": { + "reviewed": "eeb1847df7d9d58029de37225dabf963bf1a65e6", + "final": "eeb1847df7d9d58029de37225dabf963bf1a65e6" + }, + "scope": [ + "src/EulerRouter.sol", + "src/adapter/BaseAdapter.sol", + "src/adapter/CrossAdapter.sol", + "src/adapter/chainlink/AggregatorV3Interface.sol", + "src/adapter/chainlink/ChainlinkOracle.sol", + "src/adapter/chronicle/ChronicleOracle.sol", + "src/adapter/chronicle/IChronicle.sol", + "src/adapter/lido/IStEth.sol", + "src/adapter/lido/LidoOracle.sol", + "src/adapter/maker/IPot.sol", + "src/adapter/maker/SDaiOracle.sol", + "src/adapter/pyth/PythOracle.sol", + "src/adapter/redstone/RedstoneCoreOracle.sol", + "src/adapter/uniswap/UniswapV3Oracle.sol", + "src/interfaces/IPriceOracle.sol", + "src/lib/Errors.sol", + "src/lib/Governable.sol", + "src/lib/ScaleUtils.sol" + ], + "report": "https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler_Price_Oracle_Spearbit_Report_DRAFT.pdf", + "confidence": "high", + "evidence": "Executive Summary table: Commit 'eeb184...1a65e6' == OpenZeppelin-audit tag (same commit as OZ audit); doc marked DRAFT", + "signed_off": true + }, + { + "id": "yaudit-oracle-2024-comp-fixes", + "repo": "euler-xyz/euler-price-oracle", + "firm": "yAudit", + "date": "2024-07-31", + "commits": { + "reviewed": "c4074ab7a7aa0c6ffbc555391d9f0bfe1ee5fd6f", + "final": "47296ad7e479da98ede31936d05398cbf1fc330e" + }, + "scope": [ + "src/adapter/BaseAdapter.sol", + "src/adapter/uniswap/UniswapV3Oracle.sol", + "src/EulerRouter.sol", + "src/lib/Governable.sol" + ], + "report": "https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf", + "confidence": "medium", + "evidence": "No hash in doc; EPO findings #118/#205/#443 map to commits 'fix: cantina-118/205/443 (#52/#53/#54)' merged 2024-07-30; final = latest (47296ad7); reviewed = cantina-contest baseline. Derived -> medium", + "signed_off": true + }, + { + "id": "yaudit-oracle-2024-oracleupdate", + "repo": "euler-xyz/euler-price-oracle", + "firm": "yAudit", + "date": "2024-09-15", + "commits": { + "reviewed": "8c4aeedd12b987543498b772a081e8cd261072be", + "final": "2fa395536397bf0310a00d8ab39e239f6b716dd1" + }, + "scope": [ + "src/adapter/lido/LidoFundamentalOracle.sol", + "src/adapter/fixed/FixedRateOracle.sol", + "src/adapter/rate/IRateProvider.sol", + "src/adapter/rate/RateProviderOracle.sol" + ], + "report": "https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler_Price_Oracle_yAudit_OracleUpdate_Report.pdf", + "confidence": "medium", + "evidence": "Text 'commit 8c4aeedd... for the EPO repository' (review Sep 5-6 2024); fix linked only as 'pull/61' -> git log 'fix: yaudit findings (#61)' = 2fa39553 (2024-09-09). final derived -> medium", + "signed_off": true + }, + { + "id": "yaudit-oracle-2024-pendle", + "repo": "euler-xyz/euler-price-oracle", + "firm": "yAudit", + "date": "2024-10-07", + "commits": { + "reviewed": "1582bb4c15b907a0256ec9d649b3eef3ca963739", + "final": "e1bc31ebd2ee2b78bac01271db834dae912d821e" + }, + "scope": [ + "src/adapter/pendle/PendleOracle.sol" + ], + "report": "https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler_Price_Oracle_yAudit_PendleOracle_Report.pdf", + "confidence": "high", + "evidence": "Text 'limited to the latest commit, 1582bb4c...' (review 16-17 Sep 2024); sole finding 'Fixed in .../commit/e1bc31eb...' both verbatim", + "signed_off": true + }, + { + "id": "cantina-oracle-2024", + "repo": "euler-xyz/euler-price-oracle", + "firm": "Cantina", + "date": "2024-11-13", + "commits": { + "reviewed": "c4074ab7a7aa0c6ffbc555391d9f0bfe1ee5fd6f", + "final": "c4074ab7a7aa0c6ffbc555391d9f0bfe1ee5fd6f" + }, + "scope": [ + "src/EulerRouter.sol", + "src/adapter/BaseAdapter.sol", + "src/adapter/chainlink/ChainlinkOracle.sol", + "src/adapter/redstone/RedstoneCoreOracle.sol", + "src/adapter/uniswap/UniswapV3Oracle.sol" + ], + "report": "https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler%20Cantina%20Code%20Competition%20report.pdf", + "confidence": "high", + "evidence": "Finding hyperlinks embed euler-price-oracle/blob/c4074ab7... (== cantina-contest tag); contest May20-Jun17 2024; cover Nov 13, 2024. Scope = EPO files with findings (non-exhaustive)", + "signed_off": true + }, + { + "id": "electisec-oracle-2025", + "repo": "euler-xyz/euler-price-oracle", + "firm": "Electisec", + "date": "2025-02-23", + "commits": { + "reviewed": "82011641e57cc6623fb841611152e85a56df9b63", + "final": "37fba8f752214ff2895e0773404ba3427c718042" + }, + "scope": [ + "src/adapter/pendle/PendleUniversalOracle.sol", + "src/adapter/curve/CurveEMAOracle.sol" + ], + "report": "https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler_Price_Oracle_Electisec_Report.pdf", + "confidence": "high", + "evidence": "Text 'commit 82011641...for PR#78 and 37fba8f7...for PR#79' (review Feb 17-18 2025); two independent PR reviews (reviewed=PR#78, final=PR#79 per doc order, not chronology)", + "signed_off": true + }, + { + "id": "bailsec-oracle-2026", + "repo": "euler-xyz/euler-price-oracle", + "firm": "BailSec", + "date": "2026-03-11", + "commits": { + "reviewed": "6055a513adb688919ff40c09c9ec46b35df73499", + "final": "5c59a75c5e2a043ec0418e6b56833d54205fb6de" + }, + "scope": [ + "src/adapter/chainlink/ChainlinkInfrequentOraclXStocks.sol" + ], + "report": "https://github.com/euler-xyz/euler-price-oracle/blob/18a3e34d516992b38797a1c61ebbf7dd8e957dcd/audits/Euler_Price_Oracle_BailSec_Report.pdf", + "confidence": "high", + "evidence": "Project Details table: tree/6055a513 (initial) -> Resolution 1 tree/5c59a75c. Report also covers 2 evk-periphery files (out of scope here). Path uses real repo spelling 'OraclXStocks'", + "signed_off": true + }, + { + "id": "fuzzland-euler-swap-2025", + "repo": "euler-xyz/euler-swap", + "firm": "Fuzzland", + "date": "2025-02-17", + "commits": { + "reviewed": "449beb4cc188a3203eaab4a25cf134adec6ea15d", + "final": "449beb4cc188a3203eaab4a25cf134adec6ea15d" + }, + "scope": [ + "src/" + ], + "report": "https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/eulerswap-audit-report.pdf", + "confidence": "medium", + "evidence": "PDF pages 1-6 Scope table: 'commit | 449beb4cc188a3203eaab4a25cf134adec6ea15d', 'Scope | src/*.sol'. Full hash verified in euler-swap. Date is the Feb 17 2025 engagement date (no publication date printed).", + "signed_off": true, + "notes": "scope normalized 2026-07-24 from prose placeholder to path form (original: ['src/*.sol'])" + }, + { + "id": "spearbit-euler-swap-2025", + "repo": "euler-xyz/euler-swap", + "firm": "Spearbit", + "date": "2025-03-29", + "commits": { + "reviewed": "54c1af6d7891583ddc0df332002bcbc6e06bb4cd", + "final": "54c1af6d7891583ddc0df332002bcbc6e06bb4cd" + }, + "scope": [ + "src/" + ], + "report": "https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-euler-swap-050325.pdf", + "confidence": "medium", + "evidence": "PDF pages 1-6 (DRAFT): 'From Mar 3rd to Mar 10th the Cantina team conducted a review of euler-swap on commit hash 54c1af6d'. Leads Christoph Michel & Mario.eth (Spearbit), delivered via Cantina Managed. Full hash verified in euler-swap. NOTE: repo tag 'spearbit-audit' points to a DIFFERENT same-day commit 93d836b87208afa4ab0e8ba36d8048b5d7db1b5c (Mar 5 11:04, merge PR#47) - not the PDF-stated commit.", + "signed_off": true, + "notes": "scope normalized 2026-07-24 from prose placeholder to path form (original: ['(no explicit file list in report; reviewed euler-swap repo at commit; findings reference EulerSwap.sol, EulerSwapPeriphery.sol)'])" + }, + { + "id": "chainsecurity-euler-swap-2025", + "repo": "euler-xyz/euler-swap", + "firm": "ChainSecurity", + "date": "2025-03-31", + "commits": { + "reviewed": "ec46a582d7666f0c2cb333005917fdb353e52c78", + "final": "54c1af6d7891583ddc0df332002bcbc6e06bb4cd" + }, + "scope": [ + "src/EulerSwap.sol", + "src/EulerSwapPeriphery.sol", + "src/interfaces/IEulerSwap.sol", + "src/interfaces/IEulerSwapPeriphery.sol", + "src/interfaces/IUniswapV2Callee.sol" + ], + "report": "https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/ChainSecurity_EulerSwap_audit.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6 Assessment Overview/Scope table: V1 19 Feb 2025 ec46a582... (Initial); V2 5 Mar 2025 54c1af6d... (Version with Fixes). Both full hashes match tags chainsecurity-audit / chainsecurity-audit-fixes.", + "signed_off": true + }, + { + "id": "cantina-euler-swap-2025-05", + "repo": "euler-xyz/euler-swap", + "firm": "Cantina", + "date": "2025-05-03", + "commits": { + "reviewed": "a8cf4966e1357e205b9fe4d16432d8a24b40ad56", + "final": "a8cf4966e1357e205b9fe4d16432d8a24b40ad56" + }, + "scope": [ + "src/" + ], + "report": "https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-uniswap-euler-0422.pdf", + "confidence": "medium", + "evidence": "PDF pages 1-6 (DRAFT): 'From Apr 25th to Apr 29th the Cantina team conducted a review of euler-swap on commit hash a8cf4966'. Leads MiloTruck, Cryptara. Full hash verified in euler-swap. Fixes cited only as 'PR 74' (no fix commit hash printed); no named tag.", + "signed_off": true, + "notes": "scope normalized 2026-07-24 from prose placeholder to path form (original: ['(no explicit file list in report; reviewed euler-swap repo at commit; findings reference FundsLib.sol, QuoteLib.sol, EulerSwapFactory.sol, CurveLib.sol, UniswapHook)'])" + }, + { + "id": "cyfrin-euler-swap-2025", + "repo": "euler-xyz/euler-swap", + "firm": "Cyfrin", + "date": "2025-05-26", + "commits": { + "reviewed": "1022c0bb3c034d905005f4c5aee0932a66adf4f8", + "final": "c1c375f9b5b611e7e2cd722eda197750d1b13bc2" + }, + "scope": [ + "src/EulerSwap.sol", + "src/EulerSwapFactory.sol", + "src/EulerSwapPeriphery.sol", + "src/UniswapHook.sol" + ], + "report": "https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/2025-05-26-cyfrin-eulerswap-v2.0.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6: main commit '1022c0bb3c03...' (matches cyfrin-audit tag), audit May 5-9 2025; 'An additional commit, c1c375f, was reviewed after the conclusion of the engagement'. Both hashes verified in euler-swap. Scope printed as bare filenames in the Audit Scope box.", + "signed_off": true, + "notes": "scope normalized 2026-07-24 from prose placeholder to path form (original: ['EulerSwap.sol'])" + }, + { + "id": "cantina-euler-swap-v2-2025-09", + "repo": "euler-xyz/euler-swap", + "firm": "Cantina", + "date": "2025-09-18", + "commits": { + "reviewed": "6f5bde45b89818a793d3572dc8b0412daabe2343", + "final": "22bb23aa456a72ae4bde1517e73d9a54da19ac28" + }, + "scope": [ + "src/" + ], + "report": "https://github.com/euler-xyz/euler-swap/blob/81cf6dc988468fd56f690e6bc0e338a5be02d034/audits/report-cantinacode-euler-0901.pdf", + "confidence": "medium", + "evidence": "PDF pages 1-12: 'From Aug 31st to Sep 6th the Cantina team conducted a review of euler-swap on commit hash 6f5bde45' (= tag eulerswap2-cantina-audit). Fixes verified per-finding across many commits incl. 22bb23aa (= tag eulerswap2-cantina-audit-fixes), used here as final. Both verified in euler-swap.", + "signed_off": true, + "notes": "scope normalized 2026-07-24 from prose placeholder to path form (original: ['(EulerSwap v2 architecture; no explicit file list in report; reviewed euler-swap repo at commit; findings reference EulerSwapRegistry.sol, EulerSwap.sol, QuoteLib.sol, CurveLib.sol, SwapLib, UniswapHook)'])" + }, + { + "id": "enigma-dark-evk-2024", + "repo": "euler-xyz/euler-vault-kit", + "firm": "Enigma Dark", + "date": "2024-03-01", + "commits": { + "reviewed": "", + "final": "" + }, + "scope": [], + "report": "https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/EnigmaDark_EVK_report.pdf", + "confidence": "low", + "evidence": "Cover 'March, 2024' (no day); ModDate 2024-06-28. All 7 pages + links checked: NO commit hash anywhere (links target mutable 'master'); no file scope; continuous fuzzing/invariant engagement, not point-in-time. No tag. Left unresolved rather than invented", + "signed_off": true + }, + { + "id": "yaudit-evk-2024-combined", + "repo": "euler-xyz/euler-vault-kit", + "firm": "yAudit", + "date": "2024-05-05", + "commits": { + "reviewed": "7d2408dc1013b6f3149a5f08a69ded4dc99db7c8", + "final": "7d2408dc1013b6f3149a5f08a69ded4dc99db7c8" + }, + "scope": [ + "src/EVault/DToken.sol", + "src/EVault/Dispatch.sol", + "src/EVault/EVault.sol", + "src/EVault/IEVault.sol", + "src/EVault/modules/BalanceForwarder.sol", + "src/EVault/modules/Borrowing.sol", + "src/EVault/modules/Governance.sol", + "src/EVault/modules/Initialize.sol", + "src/EVault/modules/Liquidation.sol", + "src/EVault/modules/RiskManager.sol", + "src/EVault/modules/Token.sol", + "src/EVault/modules/Vault.sol", + "src/EVault/shared/AssetTransfers.sol", + "src/EVault/shared/BalanceUtils.sol", + "src/EVault/shared/Base.sol", + "src/EVault/shared/BorrowUtils.sol", + "src/EVault/shared/Cache.sol", + "src/EVault/shared/Constants.sol", + "src/EVault/shared/EVCClient.sol", + "src/EVault/shared/Errors.sol", + "src/EVault/shared/Events.sol", + "src/EVault/shared/LTVUtils.sol", + "src/EVault/shared/LiquidityUtils.sol", + "src/EVault/shared/Storage.sol", + "src/EVault/shared/lib/ConversionHelpers.sol", + "src/EVault/shared/lib/ProxyUtils.sol", + "src/EVault/shared/lib/RPow.sol", + "src/EVault/shared/lib/RevertBytes.sol", + "src/EVault/shared/lib/SafeERC20Lib.sol", + "src/EVault/shared/types/AmountCap.sol", + "src/EVault/shared/types/Assets.sol", + "src/EVault/shared/types/ConfigAmount.sol", + "src/EVault/shared/types/Flags.sol", + "src/EVault/shared/types/LTVConfig.sol", + "src/EVault/shared/types/LTVType.sol", + "src/EVault/shared/types/Owed.sol", + "src/EVault/shared/types/Shares.sol", + "src/EVault/shared/types/Snapshot.sol", + "src/EVault/shared/types/Types.sol", + "src/EVault/shared/types/UserStorage.sol", + "src/EVault/shared/types/VaultCache.sol", + "src/EVault/shared/types/VaultStorage.sol", + "src/GenericFactory/BeaconProxy.sol", + "src/GenericFactory/GenericFactory.sol", + "src/GenericFactory/MetaProxyDeployer.sol", + "src/InterestRateModels/IIRM.sol", + "src/InterestRateModels/IRMLinearKink.sol", + "src/ProductLines/BaseProductLine.sol", + "src/ProductLines/Core.sol", + "src/ProductLines/Escrow.sol", + "src/ProtocolConfig/IProtocolConfig.sol", + "src/ProtocolConfig/ProtocolConfig.sol", + "src/Synths/ERC20Collateral.sol", + "src/Synths/ESynth.sol", + "src/Synths/EulerSavingsRate.sol", + "src/Synths/IRMSynth.sol", + "src/Synths/PegStabilityModule.sol", + "src/interfaces/IBalanceTracker.sol", + "src/interfaces/IPermit2.sol", + "src/interfaces/IPriceOracle.sol" + ], + "report": "https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_EVK_report.pdf", + "confidence": "high", + "evidence": "Review Summary: EVK commit 7d2408dc... (== yAudit-audit tag). Combined EVC+EVK+EPO review. Date normalized to in-doc review-period end 2024-05-05 (EVK file PDF metadata was 2024-05-21)", + "signed_off": true + }, + { + "id": "openzeppelin-evk-2024", + "repo": "euler-xyz/euler-vault-kit", + "firm": "OpenZeppelin", + "date": "2024-05-17", + "commits": { + "reviewed": "83ea1ad97b7c561d6601b220d23ec85d67ceb297", + "final": "83ea1ad97b7c561d6601b220d23ec85d67ceb297" + }, + "scope": [ + "src/EVault/DToken.sol", + "src/EVault/Dispatch.sol", + "src/EVault/EVault.sol", + "src/EVault/IEVault.sol", + "src/EVault/modules/BalanceForwarder.sol", + "src/EVault/modules/Borrowing.sol", + "src/EVault/modules/Governance.sol", + "src/EVault/modules/Initialize.sol", + "src/EVault/modules/Liquidation.sol", + "src/EVault/modules/RiskManager.sol", + "src/EVault/modules/Token.sol", + "src/EVault/modules/Vault.sol", + "src/EVault/shared/AssetTransfers.sol", + "src/EVault/shared/BalanceUtils.sol", + "src/EVault/shared/Base.sol", + "src/EVault/shared/BorrowUtils.sol", + "src/EVault/shared/Cache.sol", + "src/EVault/shared/Constants.sol", + "src/EVault/shared/EVCClient.sol", + "src/EVault/shared/Errors.sol", + "src/EVault/shared/Events.sol", + "src/EVault/shared/LTVUtils.sol", + "src/EVault/shared/LiquidityUtils.sol", + "src/EVault/shared/Storage.sol", + "src/EVault/shared/lib/ConversionHelpers.sol", + "src/EVault/shared/lib/ProxyUtils.sol", + "src/EVault/shared/lib/RPow.sol", + "src/EVault/shared/lib/RevertBytes.sol", + "src/EVault/shared/lib/SafeERC20Lib.sol", + "src/EVault/shared/types/AmountCap.sol", + "src/EVault/shared/types/Assets.sol", + "src/EVault/shared/types/ConfigAmount.sol", + "src/EVault/shared/types/Flags.sol", + "src/EVault/shared/types/LTVConfig.sol", + "src/EVault/shared/types/LTVType.sol", + "src/EVault/shared/types/Owed.sol", + "src/EVault/shared/types/Shares.sol", + "src/EVault/shared/types/Snapshot.sol", + "src/EVault/shared/types/Types.sol", + "src/EVault/shared/types/UserStorage.sol", + "src/EVault/shared/types/VaultCache.sol", + "src/EVault/shared/types/VaultStorage.sol", + "src/GenericFactory/BeaconProxy.sol", + "src/GenericFactory/GenericFactory.sol", + "src/GenericFactory/MetaProxyDeployer.sol", + "src/InterestRateModels/IIRM.sol", + "src/InterestRateModels/IRMLinearKink.sol", + "src/ProtocolConfig/IProtocolConfig.sol", + "src/ProtocolConfig/ProtocolConfig.sol", + "src/interfaces/IBalanceTracker.sol", + "src/interfaces/IPermit2.sol", + "src/interfaces/IPriceOracle.sol" + ], + "report": "https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/OpenZeppelin_EVK_report.pdf", + "confidence": "high", + "evidence": "Cover May 17 2024; Scope 'at commit 83ea1ad' (== OpenZeppelin-audit tag); explicit 51-file scope; single commit, no fix round", + "signed_off": true + }, + { + "id": "omniscia-evk-2024", + "repo": "euler-xyz/euler-vault-kit", + "firm": "Omniscia", + "date": "2024-05-20", + "commits": { + "reviewed": "a44880b0c051bec87bd3bf35383666fd6e9053d2", + "final": "0f2192ac81e2594502980097ad72ee2629649274" + }, + "scope": [ + "src/EVault/shared/types/Assets.sol", + "src/EVault/shared/types/AmountCap.sol", + "src/EVault/shared/AssetTransfers.sol", + "src/EVault/shared/Base.sol", + "src/EVault/modules/Borrowing.sol", + "src/GenericFactory/BeaconProxy.sol", + "src/EVault/shared/BorrowUtils.sol", + "src/EVault/shared/BalanceUtils.sol", + "src/EVault/modules/BalanceForwarder.sol", + "src/EVault/shared/Cache.sol", + "src/EVault/shared/Constants.sol", + "src/EVault/shared/types/ConfigAmount.sol", + "src/EVault/shared/lib/ConversionHelpers.sol", + "src/EVault/DToken.sol", + "src/EVault/Dispatch.sol", + "src/Synths/ESynth.sol", + "src/EVault/EVault.sol", + "src/EVault/shared/Errors.sol", + "src/EVault/shared/Events.sol", + "src/EVault/shared/EVCClient.sol", + "src/Synths/ERC20Collateral.sol", + "src/Synths/EulerSavingsRate.sol", + "src/EVault/shared/types/Flags.sol", + "src/EVault/modules/Governance.sol", + "src/GenericFactory/GenericFactory.sol", + "src/Synths/IRMSynth.sol", + "src/EVault/modules/Initialize.sol", + "src/InterestRateModels/IRMLinearKink.sol", + "src/EVault/shared/types/LTVType.sol", + "src/EVault/shared/LTVUtils.sol", + "src/EVault/shared/types/LTVConfig.sol", + "src/EVault/modules/Liquidation.sol", + "src/EVault/shared/LiquidityUtils.sol", + "src/GenericFactory/MetaProxyDeployer.sol", + "src/EVault/shared/types/Owed.sol", + "src/EVault/shared/lib/ProxyUtils.sol", + "src/ProtocolConfig/ProtocolConfig.sol", + "src/Synths/PegStabilityModule.sol", + "src/EVault/shared/lib/RPow.sol", + "src/EVault/shared/lib/RevertBytes.sol", + "src/EVault/modules/RiskManager.sol", + "src/EVault/shared/types/Shares.sol", + "src/EVault/shared/Storage.sol", + "src/EVault/shared/types/Snapshot.sol", + "src/EVault/shared/lib/SafeERC20Lib.sol", + "src/EVault/modules/Token.sol", + "src/EVault/shared/types/Types.sol", + "src/EVault/shared/types/UserStorage.sol", + "src/EVault/modules/Vault.sol", + "src/EVault/shared/types/VaultCache.sol", + "src/EVault/shared/types/VaultStorage.sol" + ], + "report": "https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/Omniscia_EVK_report.pdf", + "confidence": "high", + "evidence": "Cover May 20 2024; Audit Report Revisions: a44880b0 (9 Apr, initial, == Omniscia-audit tag) / fb2dd77a6f / 0f2192ac81 (last, 16/20 May); explicit 51-file 'Contracts Assessed' table", + "signed_off": true + }, + { + "id": "openzeppelin-evk-2024-synths", + "repo": "euler-xyz/euler-vault-kit", + "firm": "OpenZeppelin", + "date": "2024-06-14", + "commits": { + "reviewed": "82dd71819d6edfd265d3f6afd31530f4206b7805", + "final": "82dd71819d6edfd265d3f6afd31530f4206b7805" + }, + "scope": [ + "src/Synths/ERC20Collateral.sol", + "src/Synths/ESynth.sol", + "src/Synths/EulerSavingsRate.sol", + "src/Synths/IRMSynth.sol", + "src/Synths/PegStabilityModule.sol" + ], + "report": "https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/OpenZeppelin_Synths_report.pdf", + "confidence": "high", + "evidence": "Cover 'Synths Audit' June 14 2024; Scope 'Synths directory ... at commit 82dd718' (== OpenZeppelin-audit-synthetics tag); explicit 5-file scope", + "signed_off": true + }, + { + "id": "chainsecurity-evk-2024", + "repo": "euler-xyz/euler-vault-kit", + "firm": "ChainSecurity", + "date": "2024-06-18", + "commits": { + "reviewed": "ae7795f7fda71c18bb79805b29bb9fd4634a5930", + "final": "55d1a1fd7d572372f1c8b9f58aba0604bda3ca4f" + }, + "scope": [ + "src/EVault/Dispatch.sol", + "src/EVault/DToken.sol", + "src/EVault/EVault.sol", + "src/EVault/IEVault.sol", + "src/EVault/modules/BalanceForwarder.sol", + "src/EVault/modules/Borrowing.sol", + "src/EVault/modules/Governance.sol", + "src/EVault/modules/Initialize.sol", + "src/EVault/modules/Liquidation.sol", + "src/EVault/modules/RiskManager.sol", + "src/EVault/modules/Token.sol", + "src/EVault/modules/Vault.sol", + "src/EVault/shared/AssetTransfers.sol", + "src/EVault/shared/BalanceUtils.sol", + "src/EVault/shared/Base.sol", + "src/EVault/shared/BorrowUtils.sol", + "src/EVault/shared/Cache.sol", + "src/EVault/shared/Constants.sol", + "src/EVault/shared/Errors.sol", + "src/EVault/shared/EVCClient.sol", + "src/EVault/shared/Events.sol", + "src/EVault/shared/LiquidityUtils.sol", + "src/EVault/shared/LTVUtils.sol", + "src/EVault/shared/Storage.sol", + "src/EVault/shared/lib/AddressUtils.sol", + "src/EVault/shared/lib/ConversionHelpers.sol", + "src/EVault/shared/lib/ProxyUtils.sol", + "src/EVault/shared/lib/RevertBytes.sol", + "src/EVault/shared/lib/RPow.sol", + "src/EVault/shared/lib/SafeERC20Lib.sol", + "src/EVault/shared/types/AmountCap.sol", + "src/EVault/shared/types/Assets.sol", + "src/EVault/shared/types/ConfigAmount.sol", + "src/EVault/shared/types/Flags.sol", + "src/EVault/shared/types/LTVConfig.sol", + "src/EVault/shared/types/Owed.sol", + "src/EVault/shared/types/Shares.sol", + "src/EVault/shared/types/Snapshot.sol", + "src/EVault/shared/types/Types.sol", + "src/EVault/shared/types/UserStorage.sol", + "src/EVault/shared/types/VaultCache.sol", + "src/EVault/shared/types/VaultStorage.sol", + "src/InterestRateModels/IIRM.sol", + "src/InterestRateModels/IRMLinearKink.sol", + "src/interfaces/IBalanceTracker.sol", + "src/interfaces/IFlashLoan.sol", + "src/interfaces/IHookTarget.sol", + "src/interfaces/IPermit2.sol", + "src/interfaces/IPriceOracle.sol", + "src/ProductLines/BaseProductLine.sol", + "src/ProductLines/Core.sol", + "src/ProductLines/Escrow.sol", + "src/ProtocolConfig/IProtocolConfig.sol", + "src/ProtocolConfig/ProtocolConfig.sol", + "src/GenericFactory/BeaconProxy.sol", + "src/GenericFactory/GenericFactory.sol", + "src/GenericFactory/MetaProxyDeployer.sol", + "src/Synths/ERC20Collateral.sol", + "src/Synths/ESynth.sol", + "src/Synths/EulerSavingsRate.sol", + "src/Synths/IRMSynth.sol", + "src/Synths/PegStabilityModule.sol" + ], + "report": "https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/ChainSecurity_EVK_report.pdf", + "confidence": "high", + "evidence": "Cover 18 Jun 2024; sec 2.1 Scope table: V1 ae7795f7 (22 Apr, Initial, == ChainSecurity-audit tag & ground truth), V2 55d1a1fd (13 Jun, first round of fixes); sec 2.1.1 explicit 61-file list. Matches supplied ground truth exactly", + "signed_off": true + }, + { + "id": "spearbit-evk-2024", + "repo": "euler-xyz/euler-vault-kit", + "firm": "Spearbit", + "date": "2024-07-05", + "commits": { + "reviewed": "2bcd7e5ba33d53d1236f5ff2d4d3f71e04c61d0d", + "final": "2bcd7e5ba33d53d1236f5ff2d4d3f71e04c61d0d" + }, + "scope": [ + "src/EVault/Dispatch.sol", + "src/EVault/IEVault.sol", + "src/EVault/modules/BalanceForwarder.sol", + "src/EVault/modules/Borrowing.sol", + "src/EVault/modules/Governance.sol", + "src/EVault/modules/Liquidation.sol", + "src/EVault/modules/RiskManager.sol", + "src/EVault/modules/Token.sol", + "src/EVault/modules/Vault.sol", + "src/EVault/shared/AssetTransfers.sol", + "src/EVault/shared/BalanceUtils.sol", + "src/EVault/shared/Base.sol", + "src/EVault/shared/BorrowUtils.sol", + "src/EVault/shared/Cache.sol", + "src/EVault/shared/Events.sol", + "src/EVault/shared/lib/ProxyUtils.sol", + "src/EVault/shared/LiquidityUtils.sol", + "src/EVault/shared/types/LTVConfig.sol", + "src/EVault/shared/types/Shares.sol", + "src/GenericFactory/GenericFactory.sol", + "src/GenericFactory/MetaProxyDeployer.sol", + "src/interfaces/IBalanceTracker.sol", + "src/Synths/ERC20Collateral.sol", + "src/Synths/ESynth.sol", + "src/Synths/EulerSavingsRate.sol", + "src/Synths/IRMSynth.sol", + "src/Synths/PegStabilityModule.sol" + ], + "report": "https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/Spearbit_EVK_report.pdf", + "confidence": "high", + "evidence": "Cover July 5 2024; commit resolved via pdftohtml hyperlink to tree/2bcd7e5b... (rev-parse ok, dated 2024-04-20). DISCREPANCY: differs from Spearbit-audit tag ae7795f7 (2 days later) - report's OWN linked commit is 2bcd7e5b; no fix round -> final=reviewed. Scope from per-finding Context links (no scope section)", + "signed_off": true + }, + { + "id": "yaudit-evk-2024-comp-fixes", + "repo": "euler-xyz/euler-vault-kit", + "firm": "yAudit", + "date": "2024-07-31", + "commits": { + "reviewed": "f6fd0ee3b454630abd961d6471beb0c7eaf1216a", + "final": "1dad88bd75b40cbce1103860f616a27c2aed314c" + }, + "scope": [ + "src/EVault/Dispatch.sol", + "src/EVault/EVault.sol", + "src/EVault/IEVault.sol", + "src/EVault/modules/Borrowing.sol", + "src/EVault/modules/Governance.sol", + "src/EVault/modules/Initialize.sol", + "src/EVault/modules/Liquidation.sol", + "src/EVault/modules/RiskManager.sol", + "src/EVault/modules/Token.sol", + "src/EVault/shared/AssetTransfers.sol", + "src/EVault/shared/BalanceUtils.sol", + "src/EVault/shared/BorrowUtils.sol", + "src/EVault/shared/Cache.sol", + "src/EVault/shared/Constants.sol", + "src/EVault/shared/Errors.sol", + "src/EVault/shared/LiquidityUtils.sol", + "src/EVault/shared/lib/SafeERC20Lib.sol", + "src/EVault/shared/types/LTVConfig.sol", + "src/GenericFactory/GenericFactory.sol", + "src/InterestRateModels/IRMLinearKink.sol", + "src/SequenceRegistry/SequenceRegistry.sol", + "src/Synths/ERC20Collateral.sol", + "src/Synths/ERC20EVCCompatible.sol", + "src/Synths/ESynth.sol", + "src/Synths/EulerSavingsRate.sol", + "src/Synths/IRMSynth.sol", + "src/Synths/PegStabilityModule.sol" + ], + "report": "https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/yAudit_competition_fixes_report.pdf", + "confidence": "medium", + "evidence": "PDF scopes 4 *-cantina-fixes repos (no direct evk hash). reviewed = cantina-contest tag; final = 1dad88bd derived via git (PR#262 cantina-contest-fixes, 2024-08-12, descends from cantina baseline; 27-file diff matches finding titles). Derived -> medium", + "signed_off": true + }, + { + "id": "certora-evk-2024", + "repo": "euler-xyz/euler-vault-kit", + "firm": "Certora", + "date": "2024-08-01", + "commits": { + "reviewed": "d674d7501853643796081591d686c64d811ad1c1", + "final": "d674d7501853643796081591d686c64d811ad1c1" + }, + "scope": [ + "src/EVault/modules/BalanceForwarder.sol", + "src/EVault/modules/RiskManager.sol", + "src/EVault/modules/Liquidation.sol", + "src/EVault/modules/Vault.sol", + "src/EVault/shared/Cache.sol", + "src/EVault/shared/LiquidityUtils.sol", + "src/EVault/shared/types/ConfigAmount.sol", + "src/ProductLines/BaseProductLine.sol", + "src/ProtocolConfig/ProtocolConfig.sol" + ], + "report": "https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/Certora_EVK_report.pdf", + "confidence": "high", + "evidence": "Cover 'August 2024' (no day -> 1st-of-month approx); Project Summary single 'Last Commit Hash' d674d750 (rev-parse ok). Manual audit covered all src/; scope list = contracts named in findings/TOC (non-exhaustive)", + "signed_off": true + }, + { + "id": "cantina-evk-2024", + "repo": "euler-xyz/euler-vault-kit", + "firm": "Cantina", + "date": "2024-11-13", + "commits": { + "reviewed": "f6fd0ee3b454630abd961d6471beb0c7eaf1216a", + "final": "f6fd0ee3b454630abd961d6471beb0c7eaf1216a" + }, + "scope": [ + "src/EVault/IEVault.sol", + "src/EVault/modules/Borrowing.sol", + "src/EVault/modules/Liquidation.sol", + "src/EVault/modules/RiskManager.sol", + "src/EVault/shared/AssetTransfers.sol", + "src/EVault/shared/Cache.sol", + "src/SequenceRegistry/SequenceRegistry.sol", + "src/Synths/ERC20Collateral.sol", + "src/Synths/ESynth.sol", + "src/Synths/IRMSynth.sol", + "src/Synths/PegStabilityModule.sol" + ], + "report": "https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/Cantina_competition_report.pdf", + "confidence": "high", + "evidence": "Cover Nov 13 2024; majority of finding Context hyperlinks resolve to euler-vault-kit/blob/f6fd0ee3... (== cantina-contest tag); contest May 20-Jun 17 2024. Scope = 11-file non-exhaustive sample from context links", + "signed_off": true + }, + { + "id": "m4rio-evk-2025-setltv", + "repo": "euler-xyz/euler-vault-kit", + "firm": "M4rio.eth", + "date": "2025-01-23", + "commits": { + "reviewed": "3e5c2fea5e5296265d5c3a513b170f74b29b74b1", + "final": "3e5c2fea5e5296265d5c3a513b170f74b29b74b1" + }, + "scope": [ + "src/EVault/modules/Governance.sol" + ], + "report": "https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/M4rio.eth_setLTV_report.pdf", + "confidence": "high", + "evidence": "Cover 'Solo review by M4rio.eth' Jan 23 2025; 'review ... on commit hash 3e5c2fea' short -> rev-parse 3e5c2fea... (dated 2025-01-23). Scope = sole finding Context (Governance.sol setLTV)", + "signed_off": true + }, + { + "id": "electisec-evk-2025-setltv", + "repo": "euler-xyz/euler-vault-kit", + "firm": "Electisec", + "date": "2025-02-04", + "commits": { + "reviewed": "233afad9155a296016201663b0628ce18cdbd680", + "final": "233afad9155a296016201663b0628ce18cdbd680" + }, + "scope": [ + "src/EVault/modules/Governance.sol" + ], + "report": "https://github.com/euler-xyz/euler-vault-kit/blob/5b98b42048ba11ae82fb62dfec06d1010c8e41e6/audits/Electisec_setLTV_report.pdf", + "confidence": "high", + "evidence": "Title 'Electisec Euler EVK PR#288 - setLTV() fix Review'; body 'review ... limited to the latest pull request commit 233afad9...' verbatim 40-hex (rev-parse ok); Scope lists single file Governance.sol", + "signed_off": true + }, + { + "id": "yaudit-deployment-polygon-avalanche", + "repo": "euler-xyz/evk-periphery", + "firm": "yAudit (Electisec)", + "date": null, + "commits": { + "reviewed": null, + "final": null + }, + "scope": [], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit_Euler_Deployment_Polygon_Avalanche_Report.pdf", + "confidence": "low", + "evidence": "PDF pages 1-14 (full doc): a deployment-feasibility review of the Euler core onto Polygon & Avalanche. No commit hash, no git URL, and no date printed anywhere. Findings mention GenericFactory.sol, LidoOracle.sol, RedstoneCoreOracle.sol only in passing (not a defined scope).", + "signed_off": true, + "notes": "scope normalized 2026-07-24 (was: ['(deployment/chain-compatibility review for Polygon & Avalanche; NO src/ file scope and NO commit hash in document; assessed categories: Opcode Support/Diff Semantics (PUSH0, Cancun), Blocks (reorgs, block time/numbering), Mempool, Other chain features (signature replay, Permit2, address derivation, deterministic deployment, precompiles), Oracles (Chainlink, Uniswap, Pyth, Chronicle, Redstone, Lido))'])" + }, + { + "id": "yaudit-evk-periphery-2024", + "repo": "euler-xyz/evk-periphery", + "firm": "yAudit (Electisec)", + "date": "2024-06-26", + "commits": { + "reviewed": "090cbba2870f7ddbbbd6d360ee35a69475ab6ff8", + "final": "090cbba2870f7ddbbbd6d360ee35a69475ab6ff8" + }, + "scope": [ + "src/BaseFactory/BaseFactory.sol", + "src/BaseFactory/interfaces/IFactory.sol", + "src/IRMFactory/EulerKinkIRMFactory.sol", + "src/IRMFactory/interfaces/IEulerKinkIRMFactory.sol", + "src/OracleFactory/AdapterRegistry.sol", + "src/OracleFactory/EulerRouterFactory.sol", + "src/OracleFactory/interfaces/IEulerRouter.sol", + "src/OracleFactory/interfaces/IEulerRouterFactory.sol", + "src/Perspectives/deployed/EscrowSingletonPerspective.sol", + "src/Perspectives/deployed/EulerDefaultClusterPerspective.sol", + "src/Perspectives/deployed/EulerFactoryPerspective.sol", + "src/Perspectives/deployed/ImmutableWhitelistPerspective.sol", + "src/Perspectives/implementation/BasePerspective.sol", + "src/Perspectives/implementation/DefaultClusterPerspective.sol", + "src/Perspectives/implementation/PerspectiveErrors.sol", + "src/Perspectives/implementation/interfaces/IPerspective.sol", + "src/Swaps/ISwapper.sol", + "src/Swaps/SwapVerifier.sol", + "src/Swaps/Swapper.sol", + "src/Swaps/handlers/BaseHandler.sol", + "src/Swaps/handlers/OneInchHandler.sol", + "src/Swaps/handlers/UniswapAutoRouterHandler.sol", + "src/Swaps/handlers/UniswapV2Handler.sol", + "src/Swaps/handlers/UniswapV3Handler.sol", + "src/Swaps/vendor/ISwapRouterV2.sol", + "src/Swaps/vendor/ISwapRouterV3.sol", + "src/Swaps/vendor/IUniswapV3SwapCallback.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6: 'This was commit 090cbba2870f7ddbbbd6d360ee35a69475ab6ff8 for the EVK Periphery repository.' Full scope tree on pp.5-6. Hash verified in evk-periphery. Date = review window end (Jun 17-26 2024); no publication date.", + "signed_off": true + }, + { + "id": "yaudit-evk-periphery-guardians-2024", + "repo": "euler-xyz/evk-periphery", + "firm": "yAudit (Electisec)", + "date": "2024-08-09", + "commits": { + "reviewed": "c8b4af83b37a49d86be379e7427ee325dfdde036", + "final": "c8b4af83b37a49d86be379e7427ee325dfdde036" + }, + "scope": [ + "src/Governor/FactoryGovernor.sol", + "src/Governor/GovernorGuardian.sol", + "src/Governor/ReadOnlyProxy.sol", + "src/HookTarget/HookTargetGuardian.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Periphery%20Guardians.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6: 'This was commit c8b4af83b37a49d86be379e7427ee325dfdde036 for the EVK Periphery repository.' Hash verified in evk-periphery. Date = review window end (Aug 8-9 2024); no publication date.", + "signed_off": true + }, + { + "id": "yaudit-hook-target-firewall-2024", + "repo": "euler-xyz/evk-periphery", + "firm": "yAudit (Electisec)", + "date": "2024-09-18", + "commits": { + "reviewed": "620f9f036018e11186b1b83114204c1801e1bb70", + "final": "620f9f036018e11186b1b83114204c1801e1bb70" + }, + "scope": [ + "src/HookTarget/HookTargetFirewall.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20Euler%20Hook%20Target%20Firewall.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6: 'the review was limited to the latest commit, 620f9f036018e11186b1b83114204c1801e1bb70'. Hash verified in evk-periphery. Date = review window end (Sep 17-18 2024); no publication date.", + "signed_off": true + }, + { + "id": "yaudit-reul-erc20wrapperlocked-2024", + "repo": "euler-xyz/evk-periphery", + "firm": "yAudit (Electisec)", + "date": "2024-10-04", + "commits": { + "reviewed": "a6a8024b90b334806c0d99b7bab3b10b45a74bc5", + "final": "a6a8024b90b334806c0d99b7bab3b10b45a74bc5" + }, + "scope": [ + "src/ERC20/deployed/RewardToken.sol", + "src/ERC20/implementation/ERC20WrapperLocked.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20rEUL%20ERC20%20Wrapper%20Locked.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6: 'This was commit a6a8024b90b334806c0d99b7bab3b10b45a74bc5 for the Euler EVK periphery ERC20 Wrapper Locked PR.' Hash verified in evk-periphery. Fixes in PR#110. Date = review window end (Oct 2-4 2024); no publication date.", + "signed_off": true + }, + { + "id": "yaudit-evk-custom-liquidator-selector-2024", + "repo": "euler-xyz/evk-periphery", + "firm": "yAudit (Electisec)", + "date": "2024-10-21", + "commits": { + "reviewed": "6c74e21ead5074df9125b1511d4613b92172bfc1", + "final": "4a4fdfdc805bcf735596cc03bc0a1a71a0a03b5e" + }, + "scope": [ + "src/AccessControl/SelectorAccessControl.sol", + "src/Governor/GovernorAccessControl.sol", + "src/HookTarget/BaseHookTarget.sol", + "src/HookTarget/HookTargetAccessControl.sol", + "src/Liquidator/CustomLiquidatorBase.sol", + "src/Liquidator/SBLiquidator.sol", + "src/Governor/FactoryGovernor.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20EVK%20Custom%20Liquidator%20%26%20Selector%20Access%20Control.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6: main scope at commit 6c74e21e...; FactoryGovernor.sol at commit ce7b05b5...; GovernorAccessControl.sol refactor at commit 4a4fdfdc... (last-reviewed). All three hashes verified in evk-periphery. Date = review window end (Oct 17-21 2024).", + "signed_off": true + }, + { + "id": "cdsecurity-erc20wrapperlocked-2024", + "repo": "euler-xyz/evk-periphery", + "firm": "CD Security", + "date": "2024-10-28", + "commits": { + "reviewed": "f81de18be410e77176e2da247d8402576e99c40b", + "final": "f81de18be410e77176e2da247d8402576e99c40b" + }, + "scope": [ + "src/ERC20/implementation/ERC20WrapperLocked.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CDSecurity%20ERC20%20Wrapper%20Locked.pdf", + "confidence": "high", + "evidence": "PDF pages 1-8: 'review commit hash - f81de18be410e77176e2da247d8402576e99c40b'; scope 'ERC20WrapperLocked.sol'. Hash verified in evk-periphery; path resolved in-repo (PDF gave bare filename). Cover date month-only 'October 2024'. No repo URL printed (repo=evk-periphery inferred+confirmed). Date reflects the engagement conclusion: the PDF's own reviewed commit f81de18b is dated 2024-10-28 and targets the PR #141 double-tiered whitelist merged 2024-10-28, so the engagement concluded late Oct 2024 (cover says only 'October 2024'); CD Security \u2014 not yAudit \u2014 is therefore the last dedicated rEUL review.", + "signed_off": true + }, + { + "id": "bailsec-erc20burnablemintable-2024", + "repo": "euler-xyz/evk-periphery", + "firm": "BailSec", + "date": "2024-12-01", + "commits": { + "reviewed": "b3ac5f126c6c0a0374374a6b7fbf18b4461f5496", + "final": "b3ac5f126c6c0a0374374a6b7fbf18b4461f5496" + }, + "scope": [ + "src/ERC20/deployed/ERC20BurnableMintable.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/BailSec%20ERC20BurnableMintable.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6 blob URL: github.com/euler-xyz/evk-periphery/blob/b3ac5f126c6c0a0374374a6b7fbf18b4461f5496/src/ERC20/deployed/ERC20BurnableMintable.sol. Hash verified in evk-periphery. Cover date month-only 'December 2024'.", + "signed_off": true + }, + { + "id": "paladin-layerzero-adapters-2025", + "repo": "euler-xyz/evk-periphery", + "firm": "Paladin Blockchain Security", + "date": "2025-01-23", + "commits": { + "reviewed": "70b26235cfa1e36627ccdca59a760411c1aa8288", + "final": "e3699ffb644bb96bfcff4fb6f0f35d11d23f6503" + }, + "scope": [ + "src/OFT/MintBurnOFTAdapter.sol", + "src/OFT/OFTAdapterUpgradeable.sol", + "src/ERC20/deployed/ERC20BurnableMintable.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/8c946bb15574c764bee054de79758b958d0130d4/audits/Paladin%20LayerZero%20Adapters.pdf", + "confidence": "high", + "evidence": "In-repo PDF 'Smart Contract Security Assessment \u2014 For LayerZero (Euler)' (added to master via PR #422 chore/paladin-report). Preliminary commit 70b26235 (introduces both adapters, 2025-01-08); resolution verified at e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers). 2 informationals: #01 acknowledged (mainnet lockbox stranding via burnable bridged tokens), #02 resolved. ERC20BurnableMintable: no issues found. This report is the covering audit for the OFT adapters.", + "signed_off": true + }, + { + "id": "electisec-adaptive-irm-2025", + "repo": "euler-xyz/evk-periphery", + "firm": "Electisec", + "date": "2025-02-05", + "commits": { + "reviewed": "52a2572ed6f23fa4e0b293d0cc2d77d8ce7f1f8c", + "final": "21f0cfdad33774d76aac77083926f0381f1dbabe" + }, + "scope": [ + "src/IRM/IRMAdaptiveCurve.sol", + "src/IRM/lib/ExpLib.sol", + "src/IRMFactory/EulerIRMAdaptiveCurveFactory.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Electisec%20Adaptive%20IRM.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6: two-phase review - PR#58 latest commit 52a2572e... (Aug 26-27 2024), PR#233 latest commit 21f0cfda... (Feb 4-5 2025, last-reviewed). Both hashes verified in evk-periphery. No single publication date; date = second review window. High-finding fix commits b279f65.../53a192fd... noted separately.", + "signed_off": true + }, + { + "id": "electisec-governor-access-control-emergency-factory-2025", + "repo": "euler-xyz/evk-periphery", + "firm": "Electisec", + "date": "2025-03-11", + "commits": { + "reviewed": "7b7a9dcb42bb517c46eead9a701eec504149edd3", + "final": "7b7a9dcb42bb517c46eead9a701eec504149edd3" + }, + "scope": [ + "src/GovernorFactory/GovernorAccessControlEmergencyFactory.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Electisec%20GovernorAccessControlEmergencyFactory.pdf", + "confidence": "high", + "evidence": "PDF pages 1-3: 'This was commit 7b7a9dcb42bb517c46eead9a701eec504149edd3' (PR#261). Hash verified in evk-periphery. Also reviewed on-chain deployments (Base block 27416679, Ethereum block 22018607). No publication date; date = review window (Mar 10-11 2025).", + "signed_off": true + }, + { + "id": "mixbytes-caprisksteward-2025", + "repo": "euler-xyz/evk-periphery", + "firm": "MixBytes", + "date": "2025-04-22", + "commits": { + "reviewed": "a438c1e910f7292adbd527b4ea72742d3f736f23", + "final": "f311fa49f4442643c4473ac46b520b1f40e99dcb" + }, + "scope": [ + "src/Governor/CapRiskSteward.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/MixBytes%20CapRiskSteward.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6 Versions Log: a438c1e9... (Initial 02.04.2025), dfaf4e94... (Re-audit 04.04.2025), f311fa49... (updates 14.04.2025, final). All three verified in evk-periphery. Report/cover date 2025-04-22.", + "signed_off": true + }, + { + "id": "mixbytes-hooktargetstakedelegator-2025", + "repo": "euler-xyz/evk-periphery", + "firm": "MixBytes", + "date": "2025-04-22", + "commits": { + "reviewed": "995449e6e960b515869f00235fdcd417ad8e08fc", + "final": "491a657e865c9ad2e6ecd1c3c20f0443e0d68422" + }, + "scope": [ + "src/HookTarget/HookTargetStakeDelegator.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/MixBytes%20HookTargetStakeDelegator.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6 Versions Log: 995449e6... (Initial 07.04.2025), 64786662... (Re-audit 14.04.2025), 491a657e... (updates 16.04.2025, final). All three verified in evk-periphery. Report/cover date 2025-04-22.", + "signed_off": true + }, + { + "id": "supremacy-irmlinearkinky-2025", + "repo": "euler-xyz/evk-periphery", + "firm": "Supremacy", + "date": "2025-06-13", + "commits": { + "reviewed": "a647325c329cb1ed398fab7cac9b8e31108c282e", + "final": "a647325c329cb1ed398fab7cac9b8e31108c282e" + }, + "scope": [ + "src/IRM/IRMLinearKinky.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Supremacy%20IRMLinearKinky.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6: 'Repository: github.com/euler-xyz/evk-periphery/blob/a647325c329cb1ed398fab7cac9b8e31108c282e/src/IRM/IRMLinearKinky.sol', 'Commit Hash: a647325c...'. Verified in evk-periphery. v1.0 Final Release 2025-06-13 (v0.1 draft 2025-06-12); single code commit.", + "signed_off": true + }, + { + "id": "cdsecurity-hooktargetmarketstatus-2025", + "repo": "euler-xyz/evk-periphery", + "firm": "CD Security", + "date": "2025-08-01", + "commits": { + "reviewed": "e3d31d4f39df5d0ab193f25a5c4ee4ff58d29f01", + "final": "5eed034a9119f5405ee045349da926fafff9e7ba" + }, + "scope": [ + "src/Chainlink/DataStreamsVerifier.sol", + "src/HookTarget/HookTargetMarketStatus.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/CD%20Security%20HookTargetMarketStatus.pdf", + "confidence": "high", + "evidence": "PDF pages 1-5: 'review commit hash - e3d31d4f...'; 'fixes review commit hash - 5eed034a...'; scope 'DataStreamsVerifier.sol, HookTargetMarketStatus.sol'. Both verified in evk-periphery; paths resolved in-repo (PDF gave bare filenames). Cover date month-only 'August 2025'. No repo URL printed.", + "signed_off": true + }, + { + "id": "cantina-evk-periphery-pr361-2025", + "repo": "euler-xyz/evk-periphery", + "firm": "Cantina", + "date": "2025-10-14", + "commits": { + "reviewed": "642602f8cb487969932d86298993f40b42727c88", + "final": "4711a8ad0f23bdc0209b7be772efa42b887e3518" + }, + "scope": [ + "src/FeeFlow/FeeFlowControllerEVK.sol", + "src/OFT/OFTFeeCollector.sol", + "src/OFT/OFTGulper.sol", + "src/Util/FeeCollectorUtil.sol", + "src/Util/FeeCollectorGulper.sol", + "src/IRM/IRMBasePremium.sol", + "src/IRM/IIRMBasePremium.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/1f83f782c91552d496232036667be81e5e046791/audits/Cantina%20Crosschain%20Fee%20Flow%20and%20Auxiliary%20Contracts.pdf", + "confidence": "medium", + "evidence": "PDF pages 1-10 (DRAFT): 'From Oct 10th to Oct 12th the Cantina team conducted a review of evk-periphery on commit hash 642602f8'; holistic re-review at 4711a8ad. Both verified in evk-periphery. WARNING: the PDF filename says 'Spearbit ERC20Synth' but the content is a Cantina Managed DRAFT titled 'Euler EVK Periphery PR 361' (FeeFlow/OFT/IRM), not Spearbit and not ERC20Synth-titled.", + "signed_off": true, + "notes": "dropped prose scope entry 2026-07-24: (no explicit scope section in report; paths above inferred f" + }, + { + "id": "electisec-erc20synth-aux-2025", + "repo": "euler-xyz/evk-periphery", + "firm": "Electisec", + "date": "2025-10-14", + "commits": { + "reviewed": "642602f8cb487969932d86298993f40b42727c88", + "final": "642602f8cb487969932d86298993f40b42727c88" + }, + "scope": [ + "src/ERC20/deployed/ERC20Synth.sol", + "src/FeeFlow/FeeFlowControllerEVK.sol", + "src/IRM/IRMBasePremium.sol", + "src/OFT/OFTFeeCollector.sol", + "src/OFT/OFTGulper.sol", + "src/Util/FeeCollectorGulper.sol", + "src/Util/FeeCollectorUtil.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Electisec%20ERC20Synth%20and%20auxiliary%20contracts.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6: 'Repository: github.com/euler-xyz/evk-periphery Commit Hash: 642602f8cb487969932d86298993f40b42727c88' with full Audit Scope tree. Verified in evk-periphery. Cover date 2025-10-14. Same PR361/commit as the Cantina PR361 report. Per-finding fix commits noted in dev responses.", + "signed_off": true + }, + { + "id": "pashov-erc4626-vault-securitize-2025", + "repo": "euler-xyz/evk-periphery", + "firm": "Pashov Audit Group", + "date": "2025-11-06", + "commits": { + "reviewed": "3d70bf28e13625d99bb3b90ab5b3d28ec2b7f264", + "final": "06c0817d1fe4dcd9f420c28085204024fdf8188d" + }, + "scope": [ + "src/Vault/deployed/ERC4626EVCCollateralSecuritize.sol", + "src/Vault/implementation/ERC4626EVC.sol", + "src/Vault/implementation/ERC4626EVCCollateral.sol", + "src/Vault/implementation/ERC4626EVCCollateralCapped.sol", + "src/Vault/implementation/ERC4626EVCCollateralFreezable.sol", + "src/VaultFactory/ERC4626EVCCollateralSecuritizeFactory.sol", + "src/VaultFactory/interfaces/IERC4626EVCCollateralSecuritizeFactory.sol", + "src/Swaps/SwapVerifier.sol", + "src/Swaps/TransferFromSender.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Pashov%20Group%20ERC4626%20and%20Vault%20Securitize.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6: 'Review commit hashes: 3d70bf28... 0467fb77... (euler-xyz/evk-periphery); Fixes review commit hash: 06c0817d...'. All verified in evk-periphery. Scope printed as bare filename chips; paths resolved in-repo. Second review commit 0467fb77dcf269be6d572bcd6427a3626a3a4e14 also listed.", + "signed_off": true + }, + { + "id": "yaudit-erc4626-vault-securitize-2025", + "repo": "euler-xyz/evk-periphery", + "firm": "yAudit (Electisec)", + "date": "2025-11-21", + "commits": { + "reviewed": "101860e5a2b6cdf469f0888faa3cad67e6236c95", + "final": "6d5a5af16773b26ff62828cab0305e9809958855" + }, + "scope": [ + "src/Swaps/SwapVerifier.sol", + "src/Swaps/TransferFromSender.sol", + "src/Vault/implementation/ERC4626EVC.sol", + "src/Vault/implementation/ERC4626EVCCollateral.sol", + "src/Vault/implementation/ERC4626EVCCollateralCapped.sol", + "src/Vault/implementation/ERC4626EVCCollateralFreezable.sol", + "src/Vault/deployed/ERC4626EVCCollateralSecuritize.sol", + "src/VaultFactory/ERC4626EVCCollateralSecuritizeFactory.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20ERC4626%20and%20Vault%20Securitize.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6: 'Repository: github.com/euler-xyz/evk-periphery/ Commit Hashes: 101860e5... / 6d5a5af1...' with explicit 8-file scope tree. Both verified in evk-periphery. Findings cite 'Fixed in: bb0bb5' so 6d5a5af1 taken as final. Cover date 2025-11-21.", + "signed_off": true + }, + { + "id": "yaudit-swapverifier-update-2026", + "repo": "euler-xyz/evk-periphery", + "firm": "yAudit (Electisec)", + "date": "2026-02-04", + "commits": { + "reviewed": "bf0185f502968049e1374631424e09517532c3e2", + "final": "bf0185f502968049e1374631424e09517532c3e2" + }, + "scope": [ + "src/Swaps/SwapVerifier.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/yAudit%20SwapVerifier%20update.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6: 'Repository: github.com/euler-xyz/evk-periphery/ Commit Hash: bf0185f502968049e1374631424e09517532c3e2' (PR#406). Verified in evk-periphery. Cover date 2026-02-04. Dev-cited fix commit b6046f4 -> b6046f44e2d3249a9ce87c9e48be4040d90a8225 (not a reviewed revision).", + "signed_off": true + }, + { + "id": "bailsec-evk-periphery-auxiliary-2026", + "repo": "euler-xyz/evk-periphery", + "firm": "BailSec", + "date": "2026-03-01", + "commits": { + "reviewed": "d2b3925ea9373b72310f95d9a350f0715f5b7e20", + "final": "87b425bfc84dca50e30f26f8d5014c722e61c8d1" + }, + "scope": [ + "src/HookTarget/HookTargetTermsOfUse.sol", + "src/Swaps/SwapVerifier.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/BailSec%20EVK%20Periphery%20Oracle%20Hook%20SwapVerifier.pdf", + "confidence": "medium", + "evidence": "PDF pages 1-6 multi-repo/multi-revision. evk-periphery: HookTargetTermsOfUse.sol initial d2b3925e... -> Res1 28682195c0823a4ec1508caa2fb7e96b00816402 -> Res2 87b425bf...; SwapVerifier.sol at eae25d38...; all evk-periphery hashes verified. euler-price-oracle: 6055a513/5c59a75c verified in euler-price-oracle checkout. reviewed set to first evk-periphery commit, final to Res2 (last). Cover date month-only 'March 2026'.", + "signed_off": true, + "notes": "dropped prose scope entry 2026-07-24: (also covers euler-price-oracle: ChainlinkInfrequentOracleXS" + }, + { + "id": "enigma-dark-swapverifier-update-2026", + "repo": "euler-xyz/evk-periphery", + "firm": "Enigma Dark", + "date": "2026-07-01", + "commits": { + "reviewed": "ad5325fe3e7e1e16f111da31f6d47d438754b18e", + "final": "469d9cfefc08b7a5e5acefb572f840864a19a8d5" + }, + "scope": [ + "src/Swaps/MigrationHelper.sol", + "src/Swaps/SwapVerifier.sol" + ], + "report": "https://github.com/euler-xyz/evk-periphery/blob/3d3b4b96109c8468198ac70a71dc73d027467927/audits/Enigma%20Dark%20SwapVerifier%20update.pdf", + "confidence": "high", + "evidence": "PDF pages 1-6: 'evk-periphery | diff ad5325fe...469d9cfe (PR #423)' covering src/Swaps/MigrationHelper.sol and src/Swaps/SwapVerifier.sol. Both short hashes resolved+verified in evk-periphery (diff base=reviewed, diff head=final). Cover date month-only 'Jul, 2026'.", + "signed_off": true + }, + { + "id": "zellic-fee-flow-2024", + "repo": "euler-xyz/fee-flow", + "firm": "Zellic", + "date": "2024-02-06", + "commits": { + "reviewed": "a16608ef753194491b270ca2616cc2189f22aca1", + "final": "0b67c0308a80835c8aa4a5d7011ed349bcbb8445" + }, + "scope": [ + "src/" + ], + "report": "https://github.com/euler-xyz/fee-flow/blob/3bee858a1568d1313f37d615953f83391a897866/audits/FeeFlow%20Zellic%20Report.pdf", + "confidence": "medium", + "evidence": "Cover/2.3 Scope table commit a16608ef... verbatim; 3.1-3.3 fixes cite a42879c0/c789fcaa/8c2767f5 (tip of origin/fix/zellic-audit-fixes, merged into 0b67c030 - the base OtterSec & Team Omega both cite). final derived via branch/merge tracing -> medium", + "signed_off": true + }, + { + "id": "ottersec-fee-flow-2024", + "repo": "euler-xyz/fee-flow", + "firm": "OtterSec", + "date": "2024-02-21", + "commits": { + "reviewed": "0b67c0308a80835c8aa4a5d7011ed349bcbb8445", + "final": "03b445222d31f60741d785c10696ce030a7fdf87" + }, + "scope": [ + "src/" + ], + "report": "https://github.com/euler-xyz/fee-flow/blob/3bee858a1568d1313f37d615953f83391a897866/audits/FeeFlow%20Ottersec%20Report.pdf", + "confidence": "high", + "evidence": "Cover Feb 21 2024 (fieldwork Feb 19-20); 02 Scope short commit 0b67c0 -> 0b67c030...; finding 'Fixed in 03b4452' -> 03b44522...; both match Team Omega full hashes exactly", + "signed_off": true + }, + { + "id": "team-omega-fee-flow-2024", + "repo": "euler-xyz/fee-flow", + "firm": "Team Omega", + "date": "2024-02-27", + "commits": { + "reviewed": "0b67c0308a80835c8aa4a5d7011ed349bcbb8445", + "final": "03b445222d31f60741d785c10696ce030a7fdf87" + }, + "scope": [ + "src/" + ], + "report": "https://github.com/euler-xyz/fee-flow/blob/3bee858a1568d1313f37d615953f83391a897866/audits/FeeFlow%20Team%20Omega%20Report.pdf", + "confidence": "high", + "evidence": "Cover 'Final Audit Report, February 27, 2024'; Scope full commit 0b67c030... (Feb 9 2024) verbatim over src/; Resolution full commit 03b44522... verbatim", + "signed_off": true + }, + { + "id": "hunter-reward-streams-2024", + "repo": "euler-xyz/reward-streams", + "firm": "Hunter Security", + "date": "2024-05-09", + "commits": { + "reviewed": "967c73de100620b83adce8897dc6b67bc74aac1c", + "final": "95783173eff4668bb177eeefd9e8a9dc1a44669c" + }, + "scope": [ + "src/BaseRewardStreams.sol", + "src/StakingRewardStreams.sol", + "src/TrackingRewardStreams.sol", + "src/interfaces/IBalanceTracker.sol", + "src/interfaces/IRewardStreams.sol" + ], + "report": "https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Hunter%20Security%20report.pdf", + "confidence": "high", + "evidence": "Cover Hunter Security v1.0 May 9 2024; Exec Summary Overview: commit 967c73de..., Resolution 95783173... (== audit-HunterSecurity tag); Scope table 5 files", + "signed_off": true + }, + { + "id": "mixbytes-reward-streams-2024", + "repo": "euler-xyz/reward-streams", + "firm": "MixBytes", + "date": "2024-05-16", + "commits": { + "reviewed": "95783173eff4668bb177eeefd9e8a9dc1a44669c", + "final": "92b946d4a089f03ac56a0735b92f1270bab215da" + }, + "scope": [ + "src/BaseRewardStreams.sol", + "src/StakingRewardStreams.sol", + "src/TrackingRewardStreams.sol" + ], + "report": "https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20MixBytes%20report.pdf", + "confidence": "high", + "evidence": "Cover MixBytes May 16 2024; Project Dashboard log: 09.05 commit 95783173 (audit), 16.05 commit 92b946d4 (reaudit, == audit-MixBytes tag); Scope 3 files", + "signed_off": true + }, + { + "id": "yaudit-reward-streams-2024-comp-fixes", + "repo": "euler-xyz/reward-streams", + "firm": "yAudit", + "date": "2024-07-31", + "commits": { + "reviewed": "4f63aea41dae996b59d0ba453326b6e97f44f680", + "final": "d124216a23fe042963a4bcc15e65b40d41a32b25" + }, + "scope": [ + "src/BaseRewardStreams.sol", + "src/StakingRewardStreams.sol", + "src/TrackingRewardStreams.sol", + "src/interfaces/IBalanceTracker.sol", + "src/interfaces/IRewardStreams.sol" + ], + "report": "https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20yAudit%20Code%20Competition%20Fixes%20report.pdf", + "confidence": "medium", + "evidence": "GitBook export, no printed date/commit (metadata 2024-07-31). Reward Streams issues #31/154/167/231/233/240/273/313/339 + DistributionStorage refactor map to 'fix: cantina NNN' commits (PRs #1-#10, 2024-07-02..07-15, final d124216); reviewed = cantina-contest tag. Derived -> medium", + "signed_off": true + }, + { + "id": "cantina-reward-streams-2024", + "repo": "euler-xyz/reward-streams", + "firm": "Cantina", + "date": "2024-11-13", + "commits": { + "reviewed": "4f63aea41dae996b59d0ba453326b6e97f44f680", + "final": "4f63aea41dae996b59d0ba453326b6e97f44f680" + }, + "scope": [ + "src/BaseRewardStreams.sol", + "src/StakingRewardStreams.sol", + "src/TrackingRewardStreams.sol" + ], + "report": "https://github.com/euler-xyz/reward-streams/blob/a63c358265bc8184a6d893e510a2c8566351d2e6/audits/Euler%20Cantina%20Code%20Competition%20report.pdf", + "confidence": "high", + "evidence": "Cover Cantina Nov 13 2024; shared Euler-v2 competition May20-Jun17 2024; no per-repo commit table in report; findings reference the 3 src files; mapped to cantina-contest tag (repo pin)", + "signed_off": true + } +] diff --git a/verify/baselines.json b/verify/baselines.json new file mode 100644 index 0000000..a92c4b4 --- /dev/null +++ b/verify/baselines.json @@ -0,0 +1,424 @@ +{ + "$comment": "Component audit baselines. ONE baseline per component: the fixes-included state of the component's LAST audit \u2014 derived by tracing post-review fix commits (fix commits are usually not stated in reports). Every deployed pin is diffed against this single baseline, restricted to componentPaths. Pins that predate the baseline carry a naturalBaseline: the audit whose fixes-included state the deployed code actually matches, plus the audits that reviewed the pin\u2192baseline delta. Derivations reference PRs/commits/tags verifiable in the public repos.", + "generated": "2026-07-25", + "components": [ + { + "component": "evc", + "repo": "euler-xyz/ethereum-vault-connector", + "keys": [ + "evc" + ], + "componentPaths": [ + "src/" + ], + "lastAudit": { + "id": "yaudit-evc-2024-comp-fixes", + "date": "2024-07-31", + "finalReviewedCommit": "084b32284ba643921f8d21bff3ddaf0c4e08d754" + }, + "baseline": { + "commit": "084b32284ba643921f8d21bff3ddaf0c4e08d754", + "date": "2024-08-12", + "derivation": "Last full-scope audit of the broadly-deployed EVC lineage: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #169 cantina-fixes with every EVC fix verified 'Fix OK' (including the operator-bypass fix a4dcf9e) \u2014 no further fixes required, so baseline = final. Registry entries dated later do not displace it: cantina-evc-2024 is the competition report whose reviewed revision (tag cantina-contest, 2024-05-20) PREDATES these fixes, and yaudit-evc-2026-setsize is a feature review (SET_MAX_ELEMENTS 10\u2192100) commissioned for the Gondor/Polymarket integration and deployed only on Polygon \u2014 it covers that pin's delta rather than anchoring the component.", + "confidence": "high" + }, + "pinNotes": { + "084b32284ba643921f8d21bff3ddaf0c4e08d754": { + "summary": "Equals the baseline \u2014 the mainnet EVC deployment IS the audited fixes-included commit." + }, + "a7d3c29ef7e4964736e47675e0588630d6afbfd7": { + "summary": "Descendant of the baseline and the last commit ever to touch src/ on origin/master \u2014 the 14-chain EVC equals current master source. Delta vs baseline: the EVCUtil onlyEVCAccountOwner enhancement (PRs #175/#177; pre-reviewed 'no issues spotted' in the comp-fixes report, and not part of the deployed EVC singleton's own runtime) and the PR #178/#179 isSignerValid exclusions (EIP-7587 precompile + 0x42 predeploy address space barred from being message signers \u2014 proactive hardening ahead of the Nov-2024 multichain deployment, mapped to no audit finding).", + "label": "EVCUtil helper + signer-exclusion hardening" + }, + "912b301f51301e586e5a7f09e48cf52bd52e9a0e": { + "summary": "Polygon-only deployment: the yaudit-evc-2026-setsize state (SET_MAX_ELEMENTS 10\u2192100 for the Gondor/Polymarket integration; 0 C/H/M/L findings, informational fixes included via PR #203). Descendant of the baseline; its delta = the 14-chain pin's delta plus exactly the set-size audit scope. The branch remains unmerged to master by design.", + "label": "set-size 10\u2192100 (audited) + hardening" + }, + "7b2f05f8f2fc093f679463209dea202e9af3b120": { + "summary": "Morph deployment: tip of the public origin/deployment-morph branch (\u201cfacilitate Morph deployment\u201d, 2025-02-13); descendant of the baseline, compiled at 0.8.24/runs 20000/cancun.", + "label": "Morph deployment-branch additions" + } + } + }, + { + "component": "evk", + "repo": "euler-xyz/euler-vault-kit", + "keys": [ + "eVaultFactory", + "eVaultImplementation", + "protocolConfig", + "sequenceRegistry" + ], + "coversModules": true, + "componentPaths": [ + "src/" + ], + "lastAudit": { + "id": "yaudit-evk-2024-comp-fixes", + "date": "2024-07-31", + "finalReviewedCommit": "1dad88bd75b40cbce1103860f616a27c2aed314c" + }, + "baseline": { + "commit": "1dad88bd75b40cbce1103860f616a27c2aed314c", + "date": "2024-08-12", + "derivation": "Last full-scope audited state of EVK: yAudit's combined Cantina-competition fixes review, whose final IS the merge of PR #262 cantina-contest-fixes with every competition fix verified \u2014 no further fixes required, so baseline = final. The 2025 M4rio/Electisec engagements were patch reviews scoped to the setLTV change (PR #288) only; they cover the descendants' delta rather than anchoring the component. Note cantina-evk-2024's registry date (2024-11-13) is the report publication date \u2014 its reviewed revision (2024-05-20) predates these fixes.", + "confidence": "high" + }, + "pinNotes": { + "9e3c760e051f5d769f7c6edb9be30198a55117d4": { + "summary": "Ethereum/Base deployment; descendant of the baseline. Entire src/ delta: one default-parameter line (ProtocolConfig protocolFeeShare 0.1e4\u21920.5e4, PR #264) \u2014 the pin merge itself is an EVC submodule refresh (PR #271). Effectively the audited fixes-included state.", + "label": "one fee-share default parameter" + }, + "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2": { + "summary": "The 15-chain deployment; descendant of the baseline, shipping WITH the setLTV patch. Delta vs baseline: the Governance.sol setLTV change (PR #288) \u2014 reviewed in full by both m4rio-evk-2025-setltv and electisec-evk-2025-setltv \u2014 plus the same one-line parameter default and the ESynth onlyEVCAccountOwner guards (PR #273; a src/ file outside the deployed contract set). Zero src/ changes exist after this pin: it equals origin/master's contract tree.", + "label": "setLTV patch (audited \u00d72) + param" + } + } + }, + { + "component": "reward-streams", + "repo": "euler-xyz/reward-streams", + "keys": [ + "balanceTracker" + ], + "componentPaths": [ + "src/" + ], + "lastAudit": { + "id": "cantina-reward-streams-2024", + "date": "2024-11-13", + "finalReviewedCommit": "4f63aea41dae996b59d0ba453326b6e97f44f680" + }, + "baseline": { + "commit": "d124216a23fe042963a4bcc15e65b40d41a32b25", + "date": "2024-07-15", + "derivation": "Cantina competition (reviewed commit 4f63aea4, 2024-05-18; 9 reward-streams findings, all Low/Info) was remediated on branch cantina-fixes ('fix: cantina NNN' commits via PRs #1\u2013#9, plus the DistributionStorage refactor PR #10); yaudit-reward-streams-2024-comp-fixes then verified this exact fix set at d124216a \u2014 every fix 'Fix OK'. d124216a is the earliest audit-verified state containing all fixes (branch merged to master via PR #25). Note the registry report dates invert the reviewed-commit chronology: by reviewed code, cantina precedes the July yAudit fixes review.", + "confidence": "high" + }, + "pinNotes": { + "9eb7b8a7fa31c275d688063c4abd07165b50b89f": { + "summary": "Descendant of the baseline; deployed src equals current origin/master. The only src delta vs the baseline is PR #26 (2024-08-06): enableReward/disableReward return bool, updateReward/claimReward return the claimed amount, new isRewardEnabled view \u2014 interface/return plumbing with no accounting change, post-dating every registry audit's reviewed commit. Also bumps the EVC submodule to v1.0.0 (the cantina-fixed EVC release), which affects compiled bytecode via inherited EVCUtil.", + "label": "claim return values + isRewardEnabled view" + } + } + }, + { + "component": "euler-earn", + "repo": "euler-xyz/euler-earn", + "keys": [ + "eulerEarnFactory", + "eulerEarnPublicAllocator" + ], + "componentPaths": [ + "src/" + ], + "lastAudit": { + "id": "pashov-euler-earn-2025", + "date": "2025-07-30", + "finalReviewedCommit": "b95775f4235fe4ea738dde226524d25f317d987c" + }, + "baseline": { + "commit": "8c768bd8c0f1456e70ebb6997250d2984001d150", + "date": "2025-08-31", + "derivation": "Post-Pashov fix window on master: PR #22 'pag-audit-fixes' (db821fa \u2014 max-deposit for zero-shares error handling) followed by the closing fix 8c768bd 'add max mint values' (2025-08-31); the only src commits after the final reviewed revision. Validated empirically: the 5-chain pin 773453b diffs EMPTY against this baseline; the 8-chain pin b2fd6e69 differs by \u00b118 lines of import-path cosmetics only.", + "confidence": "high" + }, + "pinNotes": { + "773453b1f4a6f1d27a1cd0c6d8f6ada572503b23": { + "summary": "src/ identical to the baseline (empty diff)." + }, + "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345": { + "summary": "\u00b118 lines vs baseline, import-path cosmetics only (no code change).", + "label": "import-path style only" + }, + "ba581a71245ad004d35241918946b08ba63552cd": { + "summary": "Linea 24kB size-fit variant (commit on the euler-earn deployment-linea branch, reconstructed from the Lineascan-verified source and bytecode-proven): equals 773453b1 \u2014 itself src-identical to the audited baseline \u2014 with setName/setSymbol commented out (\u201ccommented out not to exceed 24kB limit\u201d) in EulerEarn.sol and IEulerEarn.sol. Deploy-time compile: solc 0.8.26, optimizer_runs 200, evm london, via_ir.", + "label": "24kB fit: setName/setSymbol commented out" + }, + "bece7172a87551e6943a52b08c9a0117eb02c6c3": { + "summary": "Monad/Morph deployments: public euler-earn master commit (\u201cfix: absolute import paths\u201d, 2025-10-14); descendant of the baseline with import-path-style deltas only. Compiled at the repo profile (0.8.26, runs 200, via_ir) with the deploy workspace\u2019s OpenZeppelin v5.1.0.", + "label": "import-path style only" + } + } + }, + { + "component": "euler-swap-v1", + "repo": "euler-xyz/euler-swap", + "keys": [ + "eulerSwapV1Factory", + "eulerSwapV1Implementation", + "eulerSwapV1Periphery" + ], + "componentPaths": [ + "src/" + ], + "lastAudit": { + "id": "cyfrin-euler-swap-2025", + "date": "2025-05-26", + "finalReviewedCommit": "c1c375f9b5b611e7e2cd722eda197750d1b13bc2" + }, + "baseline": { + "commit": "207524c5f322df9326227bda6677580883e65531", + "date": "2025-05-23", + "derivation": "Cyfrin v2.0 report: 7 findings (0 C/H/M), the two Resolved ones carry named, Cyfrin-verified fix commits \u2014 6109f53 (unused imports, PR #96) and 05a9148 (ProtocolFee events, PR #97); the rest Acknowledged. 207524c5 (merge of PR #97, 2025-05-23) is the earliest commit containing both fixes. The registry final c1c375f9 (2025-05-14) predates the fix commits; Cyfrin's final report then verified them.", + "confidence": "high" + }, + "pinNotes": { + "b948f4052d7ab3116235ec754368b7125dbd5082": { + "summary": "Tag eulerswap-1.0 (official V1 release), descendant of the baseline. src delta: SPDX headers UNLICENSED\u2192GPL (14 files) + PR #99 event hoisting (new Events.sol; hook emits Swap with sender). No state-machine or math changes. foundry optimizer_runs raised 10000\u21921000000 post-audit, pre-deployment.", + "label": "SPDX licenses + event hoisting" + }, + "5d270c764204b896770e967c22c7b95959bf6660": { + "summary": "Monad factory/implementation pin; descendant of eulerswap-1.0 on linear master. Adds natspec-only named returns + a solmate import-path remapping fix. Zero semantic change.", + "label": "licenses/events + natspec, import fix" + }, + "98c05c56f7722887d293ef231accd689c2ea2493": { + "summary": "Monad periphery pin; descendant of 5d270c76. Adds one forge-fmt line-wrap. Zero semantic change.", + "label": "licenses/events + natspec/formatting" + }, + "c7da2f330dff3efb98b0b4e998f9b9f498b37c30": { + "summary": "Avalanche deployment: public branch fix/solmate-remapping \u2014 the eulerswap-1.0 release pin b948f405 plus one commit correcting the solmate import path in utils/ProtocolFee.sol (no code change). Compiled standalone at the repo profile (0.8.27, runs 1000000, shanghai).", + "label": "licenses/events + solmate import fix" + } + } + }, + { + "component": "euler-swap-v2", + "repo": "euler-xyz/euler-swap", + "keys": [ + "eulerSwapV2Factory", + "eulerSwapV2Implementation", + "eulerSwapV2Periphery", + "eulerSwapV2ProtocolFeeConfig", + "eulerSwapV2Registry" + ], + "componentPaths": [ + "src/" + ], + "lastAudit": { + "id": "cantina-euler-swap-v2-2025-09", + "date": "2025-09-18", + "finalReviewedCommit": "22bb23aa456a72ae4bde1517e73d9a54da19ac28" + }, + "baseline": { + "commit": "22bb23aa456a72ae4bde1517e73d9a54da19ac28", + "date": "2025-09-12", + "derivation": "Baseline = final reviewed commit. Cantina managed review (of tag eulerswap2-cantina-audit = 6f5bde45): 17 findings, 13 Fixed with every fix commit named in the report and verified as ancestors of 22bb23aa (which is itself the last fix commit), 4 Acknowledged. Repo tag eulerswap2-cantina-audit-fixes points exactly at this commit.", + "confidence": "high" + }, + "pinNotes": { + "81cf6dc988468fd56f690e6bc0e338a5be02d034": { + "summary": "Tag eulerswap-2.0 (the deployed release), descendant of the baseline with a substantive post-audit delta (+444/\u2212267 in src/): (1) the protocol-fee mechanism replacement \u2014 new EulerSwapProtocolFeeConfig singleton queried live at swap time, replacing the audited burned-in-at-install ProtocolFee model (see attention note); (2) an EIP-170 code-size refactor splitting EulerSwapManagement (delegatecall implementation) and EulerSwapBase out of EulerSwap; (3) ZeroShares handling for EulerEarn-style vaults; (4) hardening commits included at the release merge (pool locked during activate, fee-recipient/admin may not be EVC sub-accounts, fee-config events). No follow-up external review of this delta is recorded in the repository.", + "label": "fee-config redesign + code-size refactor" + } + } + }, + { + "component": "rEUL", + "repo": "euler-xyz/evk-periphery", + "keys": [ + "rEUL" + ], + "componentPaths": [ + "src/ERC20/deployed/RewardToken.sol", + "src/ERC20/implementation/ERC20WrapperLocked.sol" + ], + "lastAudit": { + "id": "cdsecurity-erc20wrapperlocked-2024", + "date": "2024-10-28", + "finalReviewedCommit": "f81de18be410e77176e2da247d8402576e99c40b" + }, + "baseline": { + "commit": "20df7d772dfa64bcb92909743a67c144c3e7460a", + "date": "2024-10-30", + "derivation": "CDSecurity's PDF states its reviewed commit is f81de18b (2024-10-28, the PR #141 double-tiered-whitelist state, which already contains all yAudit fixes from PR #110) \u2014 making CDSecurity, not yAudit, the last dedicated review despite the registry's 2024-10-01 date. Its 5 Fixed findings map 1:1 to the PR #147 'reul-fixes' commits, merged to master as 20df7d77. No later change to either component file exists anywhere on master (byte-identical through today's tip).", + "confidence": "high" + }, + "pinNotes": { + "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8": { + "summary": "Component files byte-identical to the baseline." + }, + "8c946bb15574c764bee054de79758b958d0130d4": { + "summary": "Component files byte-identical to the baseline (pin = current origin/master tip)." + }, + "21a169d7830f71fcfbee6f7ced12bf089f4fba20": { + "summary": "Component files byte-identical to the baseline (deployment-linea branch tip)." + }, + "7a23305815ccb4198c117c2d6fcfe8421fe336e3": { + "summary": "Mainnet deployment (commit on the evk-periphery deployment-mainnet-reul branch): source byte-identical to the public 2024-10-30 post-fixes state f61809fd \u2014 component files identical to the audited baseline \u2014 narrowed to the RewardToken compile unit with a no-longer-resolvable submodule reference removed. Compiled at the repo profile (0.8.24, runs 20000, cancun)." + } + } + }, + { + "component": "oracleRouterFactory", + "repo": "euler-xyz/evk-periphery", + "keys": [ + "oracleRouterFactory" + ], + "componentPaths": [ + "src/EulerRouterFactory/", + "src/OracleFactory/EulerRouterFactory.sol", + "src/OracleFactory/interfaces/IEulerRouterFactory.sol" + ], + "lastAudit": { + "id": "yaudit-evk-periphery-2024", + "date": "2024-06-26", + "finalReviewedCommit": "090cbba2870f7ddbbbd6d360ee35a69475ab6ff8" + }, + "baseline": { + "commit": "11637ffe47c2663c4dc337b28cd02aa8b4c87379", + "date": "2024-06-24", + "derivation": "yAudit's EVK Periphery review scope explicitly lists src/OracleFactory/ (the factory's pre-rename path). Its single factory finding (Low-1, router deployments not recorded) carries 'Fixed: 11637ff' in the report itself \u2014 baseline = that fix commit (exactly +1 line over the reviewed revision). No later periphery audit re-covered the factory shell (Cantina PR361 = eUSD stack; BailSec 2026 = oracle/hook/SwapVerifier).", + "confidence": "high" + }, + "pinNotes": { + "05b0acb8bfb64e663293ab8b236c72c6b3df86ae": { + "summary": "Factory blobs identical across all four deployed pins. Delta vs baseline: the src/OracleFactory\u2192src/EulerRouterFactory rename (content-neutral) and +10/\u22121 in EulerRouterFactory.sol \u2014 commit 59243614 threading the EVC address through the factory constructor into the embedded EulerRouter. That pass-through mirrors the router's EVC integration, which WAS audited on the oracle side (Cantina finding 443 fix + onlyEVCAccountOwner enhancement, approved by yaudit-oracle-2024-comp-fixes); the factory shell itself was not re-reviewed after this change.", + "label": "EVC constructor pass-through" + }, + "96b83f80ded9ac3f28bfce871b55917e360b9159": { + "summary": "Identical factory delta to the mainnet pin (same blobs).", + "label": "EVC constructor pass-through" + }, + "edaf96e32ebe6cb96ae30add934d74fa1d092ff6": { + "summary": "Identical factory delta to the mainnet pin (same blobs).", + "label": "EVC constructor pass-through" + }, + "21a169d7830f71fcfbee6f7ced12bf089f4fba20": { + "summary": "Identical factory delta to the mainnet pin (same blobs).", + "label": "EVC constructor pass-through" + } + }, + "libComponents": [ + { + "repo": "euler-xyz/euler-price-oracle", + "gitlinkPath": "lib/euler-price-oracle", + "componentPaths": [ + "src/EulerRouter.sol", + "src/lib/Governable.sol", + "src/lib/Errors.sol", + "src/interfaces/IPriceOracle.sol" + ], + "lastAudit": { + "id": "yaudit-oracle-2024-comp-fixes", + "date": "2024-07-31", + "finalReviewedCommit": "47296ad7e479da98ede31936d05398cbf1fc330e" + }, + "baseline": { + "commit": "47296ad7e479da98ede31936d05398cbf1fc330e", + "date": "2024-07-30", + "derivation": "The factory embeds EulerRouter creation code from this submodule. Last audit covering EulerRouter.sol is yaudit-oracle-2024-comp-fixes: its final contains the Cantina-443 router fix (EVC-aware constructor + onlyEVCAccountOwner on governance functions) marked 'Fix OK' with no further fixes, so baseline = final. Every later oracle-repo audit (oracleupdate, Pendle, Electisec 2025, BailSec 2026) is adapters-only. EulerRouter.sol has been frozen since 2024-08-16; all three distinct deployed gitlinks share an identical router blob, differing from the baseline only by a relative-imports cleanup (#57).", + "confidence": "high" + } + } + ] + }, + { + "component": "eulOFTAdapter", + "repo": "euler-xyz/evk-periphery", + "keys": [ + "eulOFTAdapter" + ], + "componentPaths": [ + "src/OFT/MintBurnOFTAdapter.sol", + "src/OFT/OFTAdapterUpgradeable.sol" + ], + "lastAudit": { + "id": "paladin-layerzero-adapters-2025", + "date": "2025-01-23", + "finalReviewedCommit": "e3699ffb644bb96bfcff4fb6f0f35d11d23f6503" + }, + "baseline": { + "commit": "e3699ffb644bb96bfcff4fb6f0f35d11d23f6503", + "date": "2025-01-25", + "derivation": "Paladin Blockchain Security's LayerZero-adapters assessment (audits/Paladin LayerZero Adapters.pdf) reviewed MintBurnOFTAdapter + OFTAdapterUpgradeable (+ ERC20BurnableMintable) at 70b26235 with two informationals: #01 acknowledged, #02 resolved by e3699ffb ('fix: Paladin audit Issue #02', _disableInitializers on the upgradeable implementation). Baseline = that resolution commit. Neither adapter file has been modified since (verified through origin/master).", + "confidence": "high" + }, + "pinNotes": { + "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8": { + "summary": "Adapter files blob-identical to the baseline." + }, + "21a169d7830f71fcfbee6f7ced12bf089f4fba20": { + "summary": "Adapter files blob-identical to the baseline (deployment-linea tip)." + }, + "ccd2debce48ed857c7766bb1955591cfac996d91": { + "summary": "Adapter files blob-identical to the baseline; as the mainnet proxy implementation it carries the Paladin #02 fix (_disableInitializers). The Oct-2025 OFT fee-collector workstream around this commit touched only OFTFeeCollector/OFTGulper, not the adapters." + } + } + }, + { + "component": "EUL-bridged", + "repo": "euler-xyz/evk-periphery", + "keys": [ + "EUL" + ], + "componentPaths": [ + "src/ERC20/deployed/ERC20BurnableMintable.sol" + ], + "lastAudit": { + "id": "paladin-layerzero-adapters-2025", + "date": "2025-01-23", + "finalReviewedCommit": "e3699ffb644bb96bfcff4fb6f0f35d11d23f6503" + }, + "baseline": { + "commit": "e3699ffb644bb96bfcff4fb6f0f35d11d23f6503", + "date": "2025-01-25", + "derivation": "ERC20BurnableMintable (the bridged EUL) was in Paladin's assessed-contracts list with 'no issues found', making Paladin \u2014 not the Dec-2024 BailSec single-file audit (one acknowledged governance/centralization finding, no change) \u2014 the last covering audit; baseline = Paladin's resolution commit. Only three source revisions of the file have ever existed: the BailSec-reviewed original (b3ac5f12), a natspec-only revision (the Paladin-audited state), and a 2025-09-29 revision adding 'virtual' to mint() for ERC20Synth overriding \u2014 no behavior change to this contract.", + "confidence": "high" + }, + "pinNotes": { + "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8": { + "summary": "Carries the Paladin-audited source revision (natspec blob) \u2014 byte-identical to the baseline." + }, + "8c946bb15574c764bee054de79758b958d0130d4": { + "summary": "Post-2025-09 revision: delta vs baseline is the 'virtual' keyword on mint() (ERC20Synth enablement) \u2014 no behavior change.", + "label": "mint() gains 'virtual' (no behavior change)" + }, + "21a169d7830f71fcfbee6f7ced12bf089f4fba20": { + "summary": "Post-2025-09 revision: same single-keyword delta as above.", + "label": "mint() gains 'virtual' (no behavior change)" + } + } + }, + { + "component": "swapVerifier", + "repo": "euler-xyz/evk-periphery", + "keys": [ + "swapVerifier" + ], + "componentPaths": [ + "src/Swaps/SwapVerifier.sol", + "src/Swaps/MigrationHelper.sol", + "src/Swaps/TransferFromSender.sol" + ], + "lastAudit": { + "id": "enigma-dark-swapverifier-update-2026", + "date": "2026-07-01", + "finalReviewedCommit": "469d9cfefc08b7a5e5acefb572f840864a19a8d5" + }, + "baseline": { + "commit": "469d9cfefc08b7a5e5acefb572f840864a19a8d5", + "date": "2026-07-07", + "derivation": "Baseline = final reviewed commit. Enigma Dark reviewed exactly the PR #423 diff (MigrationHelper + SwapVerifier re-parenting) with ZERO findings at every severity, so no fix window exists. Only non-semantic commits touch src/Swaps afterwards (forge-fmt). The repository mainline is the development branch.", + "confidence": "high" + }, + "pinNotes": { + "eae25d382bb58aaaaa9f1a3a55567af993ce32be": { + "naturalBaseline": { + "auditId": "bailsec-evk-periphery-auxiliary-2026", + "justification": "BailSec's March-2026 scope table pins SwapVerifier.sol at EXACTLY this commit (sole SwapVerifier finding: one acknowledged informational). The pin also contains the yaudit-swapverifier-update-2026 fix (b6046f44, cited verbatim in that report), so it is a doubly audit-pinned state. The pin\u2192baseline delta is precisely the Enigma-Dark-reviewed refactor: TransferFromSender folded into the new MigrationHelper parent, with no logic change to the verify functions." + }, + "label": "pre-refactor state (audit-pinned)" + }, + "edaf96e32ebe6cb96ae30add934d74fa1d092ff6": { + "summary": "Descendant of the baseline by 3 days (the merge adding the Enigma report PDF). src/Swaps delta is 100% non-semantic forge-fmt re-wrapping. This IS the Enigma-fixes-included state as deployed on 13 chains.", + "label": "formatting only" + }, + "e7337a33cb2339de7bf19d41a765c426cfe71be2": { + "summary": "Linea deployment (commit on the evk-periphery deployment-linea-periphery branch, reconstructed from the Lineascan compiler input and bytecode-proven): source byte-identical to edaf96e3 \u2014 the Enigma-fixes state \u2014 restricted to the SwapVerifier/MigrationHelper compile unit with the deploy settings (0.8.24, runs 10000, london).", + "label": "formatting only" + } + } + } + ] +} diff --git a/verify/manifest.json b/verify/manifest.json new file mode 100644 index 0000000..67e9ef6 --- /dev/null +++ b/verify/manifest.json @@ -0,0 +1,6299 @@ +{ + "1": { + "EUL": { + "note": "Canonical EUL governance token: contract Eul (contracts/governance/Eul.sol) in euler-xyz/euler-governance \u2014 an OpenZeppelin-based ERC20 with Votes/Permit and AccessControl, plus a treasury mint restricted to at most 2.718% of supply per year. Deployed at the end of 2021 (last source change 2021-12-30, commit 1249ea8b) and in continuous use since; documented here as provenance context rather than re-proven from a commit pin. BailSec performed a retrospective re-audit of exactly the deployed revision in June 2025 (bailsec-eul-erc20-2025: 4 informational findings, all acknowledged \u2014 the deployed contract is immutable). This token is the lock/unlock asset held by the mainnet OFT adapter; the bridged EUL on all other chains is the separate ERC20BurnableMintable, bytecode-proven in those chains\u2019 reports.", + "repo": "euler-xyz/euler-governance", + "verified": "canonical" + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 12330, + "origin": "hint+explorer", + "strippedSha256": "48762e01048ffb0f0ecdbe25a09b46310fa8252a9b7eaaad17e002ca62dbb6d8" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+explorer", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+explorer", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "ccd2debce48ed857c7766bb1955591cfac996d91", + "contractName": "OFTAdapterUpgradeable", + "evidence": { + "codeSize": 13374, + "origin": "hist+native", + "strippedSha256": "e74a0c71c8e108ad4297b039a9e1ea9a20724761df6e1d9fdc7f8a9775f515f1" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "proxy": { + "address": "0x4d7e09f73843Bd4735AaF7A74b6d877bac75a531", + "implementation": "0x3Bf1bD5DB4457d22A85d45791B6291b98D0fC5b5", + "note": "addresses/1/BridgeAddresses.json points at the proxy; the verified bytecode is the OFTAdapterUpgradeable implementation behind it. Upgradeability governed by the proxy admin.", + "type": "TransparentUpgradeableProxy (EIP-1967)" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24408, + "origin": "hint+explorer", + "strippedSha256": "c9ee150eb7d0223886b2ba10217238e3947c9bdef1cbe97ba978e6ebf77355c3" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "hint+explorer", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Factory": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 8305, + "origin": "hint+native", + "strippedSha256": "7c9a247e972a8a3c9fcdeacc4716b1614d613dc969016a2bae4e142396e082bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Implementation": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 24313, + "origin": "hint+native", + "strippedSha256": "20cae9a429cf62fe9cbbc90acc8fa4529a2e08f8ff0b9c34413015bdd9215ce6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Periphery": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2422, + "origin": "hint+native", + "strippedSha256": "703cfc72cd6c5fcfe53371822c5670cc72bce7aa91a5976ee254292b5e3f3b24" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3872, + "origin": "hint+native", + "strippedSha256": "4bdd5d473028a3dc1c724eec0c1c60f2dc20e0d341f25dce5267305934d39e85" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23365, + "origin": "hint+native", + "strippedSha256": "408124d9963c57097485489405479fd6df2a8e413f32e31492eb1dd5e8895aa6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2534, + "origin": "hint+native", + "strippedSha256": "f98bd760c3818f32272f4c5bc9485b83d34e9a557d0443dca200e52eb2cdadaa" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3599, + "origin": "hint+native", + "strippedSha256": "83e2e2c4d440ed1073480505822963a4600d98c878a9b65cf90a81ecdd9984bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9419, + "origin": "hint+native", + "strippedSha256": "42c58b74bd40be0268f5ea0b37691df2a74b60d9ac3124a2148a08ad7d4c9eb4" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "084b32284ba643921f8d21bff3ddaf0c4e08d754", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 21989, + "origin": "hint+explorer", + "strippedSha256": "5b4709069f7cb9c6e59f56f3cc9b06ba0fef54680d2d783242826d6ff9b0f0fd" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "05b0acb8bfb64e663293ab8b236c72c6b3df86ae", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6800, + "origin": "gitlink-bump", + "strippedSha256": "fd6ae5667a6512931642e60dda5a0f48f6e4828bcb61b53aed57e1947b1181d0" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "hint+explorer", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "7a23305815ccb4198c117c2d6fcfe8421fe336e3", + "contractName": "RewardToken", + "evidence": { + "codeSize": 11181, + "origin": "mainnet-explorer-input-reconstructed-unit-on-f61809fd", + "strippedSha256": "8d4a505819ca1d05e1a1526bf0195a8a1d20e4aac24cd8bc5e7cdeda3df8f8cf" + }, + "profile": { + "context": "explorer-settings", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "hint+explorer", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 5586, + "origin": "hint+native", + "strippedSha256": "2fc2cdd1b6e45a1d03326395d392a7418aa02fd05c71dbf5d845bcc7154354eb" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "130": { + "EUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 11981, + "origin": "ovr:dc3be15-v5.1.0", + "strippedSha256": "47294620c90c9199e0f7a39434092ca19f03307bc7b3e28dd32f37d839ae16db", + "submoduleOverrides": [ + { + "path": "lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/openzeppelin-contracts", + "ref": "v5.1.0" + } + ] + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 100000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+era", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+era", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12615, + "origin": "hint+native", + "strippedSha256": "1036d1c0fbc36f8f16e64f9c1d9afdad98eab38cb9a0d678ebc1abcbe11f4baa" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "773453b1f4a6f1d27a1cd0c6d8f6ada572503b23", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24408, + "origin": "hint+native", + "strippedSha256": "c9ee150eb7d0223886b2ba10217238e3947c9bdef1cbe97ba978e6ebf77355c3" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "hint+native", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Factory": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 8305, + "origin": "hint+native", + "strippedSha256": "7c9a247e972a8a3c9fcdeacc4716b1614d613dc969016a2bae4e142396e082bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Implementation": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 24313, + "origin": "hint+native", + "strippedSha256": "20cae9a429cf62fe9cbbc90acc8fa4529a2e08f8ff0b9c34413015bdd9215ce6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Periphery": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2422, + "origin": "hint+native", + "strippedSha256": "703cfc72cd6c5fcfe53371822c5670cc72bce7aa91a5976ee254292b5e3f3b24" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3872, + "origin": "hint+native", + "strippedSha256": "4bdd5d473028a3dc1c724eec0c1c60f2dc20e0d341f25dce5267305934d39e85" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23365, + "origin": "hint+native", + "strippedSha256": "408124d9963c57097485489405479fd6df2a8e413f32e31492eb1dd5e8895aa6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2534, + "origin": "hint+native", + "strippedSha256": "f98bd760c3818f32272f4c5bc9485b83d34e9a557d0443dca200e52eb2cdadaa" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3599, + "origin": "hint+native", + "strippedSha256": "83e2e2c4d440ed1073480505822963a4600d98c878a9b65cf90a81ecdd9984bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9419, + "origin": "hint+native", + "strippedSha256": "42c58b74bd40be0268f5ea0b37691df2a74b60d9ac3124a2148a08ad7d4c9eb4" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "a7d3c29ef7e4964736e47675e0588630d6afbfd7", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22050, + "origin": "hint+era", + "strippedSha256": "b12f6d72b8c5547a8a77595732e64e7b3e7f432357252ce4b13015605877c936" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "96b83f80ded9ac3f28bfce871b55917e360b9159", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "gitlink-bump", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "hint+native", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "hint+native", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "hint+native", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 5586, + "origin": "hint+native", + "strippedSha256": "2fc2cdd1b6e45a1d03326395d392a7418aa02fd05c71dbf5d845bcc7154354eb" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "137": { + "EUL": { + "commit": "8c946bb15574c764bee054de79758b958d0130d4", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 11981, + "origin": "polygon-explorer-input-src-9eb7b8a7-deps-blob-matched", + "strippedSha256": "da5a2a717f625b7bae655da586c5abce54ad0e718d693aea8001e24ba5bfba64", + "submoduleOverrides": [ + { + "path": "lib/ethereum-vault-connector", + "ref": "dce4f7e9817b4c770cb5a4831c7094d32dbc1621" + }, + { + "path": "lib/openzeppelin-contracts", + "ref": "69c8def5f222ff96f2b5beff05dfba996368aa79" + } + ] + }, + "profile": { + "context": "explorer-settings", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+explorer", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+explorer", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "912b301f51301e586e5a7f09e48cf52bd52e9a0e", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22050, + "origin": "setsize-branch+cancun", + "strippedSha256": "f4ec720343119658712ff6b94485810b002df7c7e1fa53d1d51c2e42b136b5c9" + }, + "profile": { + "context": "ethereum-vault-connector", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "96b83f80ded9ac3f28bfce871b55917e360b9159", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "gitlink-bump", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "hint+explorer", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "8c946bb15574c764bee054de79758b958d0130d4", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "hint+native", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "hint+explorer", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "eae25d382bb58aaaaa9f1a3a55567af993ce32be", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 3882, + "origin": "hist+native", + "strippedSha256": "9469decdb8d2280ac3dee6e320c52d16bcd164d10bf25d0add3000bd5be673b7" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "143": { + "EUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 11981, + "origin": "ovr:dc3be15-v5.1.0", + "strippedSha256": "47294620c90c9199e0f7a39434092ca19f03307bc7b3e28dd32f37d839ae16db", + "submoduleOverrides": [ + { + "path": "lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/openzeppelin-contracts", + "ref": "v5.1.0" + } + ] + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 100000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+era", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+era", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12615, + "origin": "hint+native", + "strippedSha256": "1036d1c0fbc36f8f16e64f9c1d9afdad98eab38cb9a0d678ebc1abcbe11f4baa" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "bece7172a87551e6943a52b08c9a0117eb02c6c3", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24397, + "origin": "monad-explorer-input-src-bece7172-oz-v5.1.0", + "strippedSha256": "c65c6dcf454964007e86648e08ee776371297fa604e88fdc17e940f809536a5e", + "submoduleOverrides": [ + { + "path": "lib/openzeppelin-contracts", + "ref": "69c8def5f222ff96f2b5beff05dfba996368aa79" + } + ] + }, + "profile": { + "context": "explorer-settings", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "pool(n=6)", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Factory": { + "commit": "5d270c764204b896770e967c22c7b95959bf6660", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 8305, + "origin": "hint+native", + "strippedSha256": "7c9a247e972a8a3c9fcdeacc4716b1614d613dc969016a2bae4e142396e082bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Implementation": { + "commit": "5d270c764204b896770e967c22c7b95959bf6660", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 24313, + "origin": "hint+native", + "strippedSha256": "20cae9a429cf62fe9cbbc90acc8fa4529a2e08f8ff0b9c34413015bdd9215ce6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Periphery": { + "commit": "98c05c56f7722887d293ef231accd689c2ea2493", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2422, + "origin": "hint+native", + "strippedSha256": "703cfc72cd6c5fcfe53371822c5670cc72bce7aa91a5976ee254292b5e3f3b24" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "a7d3c29ef7e4964736e47675e0588630d6afbfd7", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22050, + "origin": "hint+era", + "strippedSha256": "b12f6d72b8c5547a8a77595732e64e7b3e7f432357252ce4b13015605877c936" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "96b83f80ded9ac3f28bfce871b55917e360b9159", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "gitlink-bump", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "hint+native", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "hint+native", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "hint+native", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 5586, + "origin": "hint+native", + "strippedSha256": "2fc2cdd1b6e45a1d03326395d392a7418aa02fd05c71dbf5d845bcc7154354eb" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "146": { + "EUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 11981, + "origin": "ovr:dc3be15-v5.1.0", + "strippedSha256": "47294620c90c9199e0f7a39434092ca19f03307bc7b3e28dd32f37d839ae16db", + "submoduleOverrides": [ + { + "path": "lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/openzeppelin-contracts", + "ref": "v5.1.0" + } + ] + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 100000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+explorer", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+explorer", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12615, + "origin": "hint+native", + "strippedSha256": "1036d1c0fbc36f8f16e64f9c1d9afdad98eab38cb9a0d678ebc1abcbe11f4baa" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "773453b1f4a6f1d27a1cd0c6d8f6ada572503b23", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24408, + "origin": "hint+explorer", + "strippedSha256": "c9ee150eb7d0223886b2ba10217238e3947c9bdef1cbe97ba978e6ebf77355c3" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "hint+explorer", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Factory": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 8305, + "origin": "hint+native", + "strippedSha256": "7c9a247e972a8a3c9fcdeacc4716b1614d613dc969016a2bae4e142396e082bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Implementation": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 24313, + "origin": "hint+native", + "strippedSha256": "20cae9a429cf62fe9cbbc90acc8fa4529a2e08f8ff0b9c34413015bdd9215ce6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Periphery": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2422, + "origin": "hint+native", + "strippedSha256": "703cfc72cd6c5fcfe53371822c5670cc72bce7aa91a5976ee254292b5e3f3b24" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3872, + "origin": "hint+native", + "strippedSha256": "4bdd5d473028a3dc1c724eec0c1c60f2dc20e0d341f25dce5267305934d39e85" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23365, + "origin": "hint+native", + "strippedSha256": "408124d9963c57097485489405479fd6df2a8e413f32e31492eb1dd5e8895aa6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2534, + "origin": "hint+native", + "strippedSha256": "f98bd760c3818f32272f4c5bc9485b83d34e9a557d0443dca200e52eb2cdadaa" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3599, + "origin": "hint+native", + "strippedSha256": "83e2e2c4d440ed1073480505822963a4600d98c878a9b65cf90a81ecdd9984bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9419, + "origin": "hint+native", + "strippedSha256": "42c58b74bd40be0268f5ea0b37691df2a74b60d9ac3124a2148a08ad7d4c9eb4" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "a7d3c29ef7e4964736e47675e0588630d6afbfd7", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22050, + "origin": "hint+explorer", + "strippedSha256": "b12f6d72b8c5547a8a77595732e64e7b3e7f432357252ce4b13015605877c936" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "96b83f80ded9ac3f28bfce871b55917e360b9159", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "gitlink-bump", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "hint+explorer", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "hint+native", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "hint+explorer", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 5586, + "origin": "hint+native", + "strippedSha256": "2fc2cdd1b6e45a1d03326395d392a7418aa02fd05c71dbf5d845bcc7154354eb" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "1923": { + "EUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 12330, + "origin": "hint+native", + "strippedSha256": "48762e01048ffb0f0ecdbe25a09b46310fa8252a9b7eaaad17e002ca62dbb6d8" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 100000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+era", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+era", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12615, + "origin": "hint+native", + "strippedSha256": "1036d1c0fbc36f8f16e64f9c1d9afdad98eab38cb9a0d678ebc1abcbe11f4baa" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "773453b1f4a6f1d27a1cd0c6d8f6ada572503b23", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24408, + "origin": "hint+native", + "strippedSha256": "c9ee150eb7d0223886b2ba10217238e3947c9bdef1cbe97ba978e6ebf77355c3" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "hint+native", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Factory": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 8305, + "origin": "hint+native", + "strippedSha256": "7c9a247e972a8a3c9fcdeacc4716b1614d613dc969016a2bae4e142396e082bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Implementation": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 24313, + "origin": "hint+native", + "strippedSha256": "20cae9a429cf62fe9cbbc90acc8fa4529a2e08f8ff0b9c34413015bdd9215ce6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Periphery": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2422, + "origin": "hint+native", + "strippedSha256": "703cfc72cd6c5fcfe53371822c5670cc72bce7aa91a5976ee254292b5e3f3b24" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3872, + "origin": "hint+native", + "strippedSha256": "4bdd5d473028a3dc1c724eec0c1c60f2dc20e0d341f25dce5267305934d39e85" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23365, + "origin": "hint+native", + "strippedSha256": "408124d9963c57097485489405479fd6df2a8e413f32e31492eb1dd5e8895aa6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2534, + "origin": "hint+native", + "strippedSha256": "f98bd760c3818f32272f4c5bc9485b83d34e9a557d0443dca200e52eb2cdadaa" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3599, + "origin": "hint+native", + "strippedSha256": "83e2e2c4d440ed1073480505822963a4600d98c878a9b65cf90a81ecdd9984bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9419, + "origin": "hint+native", + "strippedSha256": "42c58b74bd40be0268f5ea0b37691df2a74b60d9ac3124a2148a08ad7d4c9eb4" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "a7d3c29ef7e4964736e47675e0588630d6afbfd7", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22050, + "origin": "hint+era", + "strippedSha256": "b12f6d72b8c5547a8a77595732e64e7b3e7f432357252ce4b13015605877c936" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "96b83f80ded9ac3f28bfce871b55917e360b9159", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "gitlink-bump", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "hint+native", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "hint+native", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "hint+native", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "eae25d382bb58aaaaa9f1a3a55567af993ce32be", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 3882, + "origin": "hist+native", + "strippedSha256": "9469decdb8d2280ac3dee6e320c52d16bcd164d10bf25d0add3000bd5be673b7" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "239": { + "EUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 11981, + "origin": "ovr:dc3be15-v5.1.0", + "strippedSha256": "47294620c90c9199e0f7a39434092ca19f03307bc7b3e28dd32f37d839ae16db", + "submoduleOverrides": [ + { + "path": "lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/openzeppelin-contracts", + "ref": "v5.1.0" + } + ] + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 100000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+era", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+era", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12615, + "origin": "hint+native", + "strippedSha256": "1036d1c0fbc36f8f16e64f9c1d9afdad98eab38cb9a0d678ebc1abcbe11f4baa" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24408, + "origin": "hint+native", + "strippedSha256": "c9ee150eb7d0223886b2ba10217238e3947c9bdef1cbe97ba978e6ebf77355c3" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "hint+native", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Factory": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 8305, + "origin": "hint+native", + "strippedSha256": "7c9a247e972a8a3c9fcdeacc4716b1614d613dc969016a2bae4e142396e082bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Implementation": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 24313, + "origin": "hint+native", + "strippedSha256": "20cae9a429cf62fe9cbbc90acc8fa4529a2e08f8ff0b9c34413015bdd9215ce6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Periphery": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2422, + "origin": "hint+native", + "strippedSha256": "703cfc72cd6c5fcfe53371822c5670cc72bce7aa91a5976ee254292b5e3f3b24" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3872, + "origin": "hint+native", + "strippedSha256": "4bdd5d473028a3dc1c724eec0c1c60f2dc20e0d341f25dce5267305934d39e85" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23365, + "origin": "hint+native", + "strippedSha256": "408124d9963c57097485489405479fd6df2a8e413f32e31492eb1dd5e8895aa6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2534, + "origin": "hint+native", + "strippedSha256": "f98bd760c3818f32272f4c5bc9485b83d34e9a557d0443dca200e52eb2cdadaa" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3599, + "origin": "hint+native", + "strippedSha256": "83e2e2c4d440ed1073480505822963a4600d98c878a9b65cf90a81ecdd9984bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9419, + "origin": "hint+native", + "strippedSha256": "42c58b74bd40be0268f5ea0b37691df2a74b60d9ac3124a2148a08ad7d4c9eb4" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "a7d3c29ef7e4964736e47675e0588630d6afbfd7", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22050, + "origin": "hint+era", + "strippedSha256": "b12f6d72b8c5547a8a77595732e64e7b3e7f432357252ce4b13015605877c936" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "96b83f80ded9ac3f28bfce871b55917e360b9159", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "gitlink-bump", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "hint+native", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "hint+native", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "hint+native", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 5586, + "origin": "hint+native", + "strippedSha256": "2fc2cdd1b6e45a1d03326395d392a7418aa02fd05c71dbf5d845bcc7154354eb" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "2818": { + "EUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 11981, + "origin": "ovr:dc3be15-v5.1.0", + "strippedSha256": "47294620c90c9199e0f7a39434092ca19f03307bc7b3e28dd32f37d839ae16db", + "submoduleOverrides": [ + { + "path": "lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/openzeppelin-contracts", + "ref": "v5.1.0" + } + ] + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 100000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+era", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+era", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12615, + "origin": "hint+native", + "strippedSha256": "1036d1c0fbc36f8f16e64f9c1d9afdad98eab38cb9a0d678ebc1abcbe11f4baa" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "bece7172a87551e6943a52b08c9a0117eb02c6c3", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24397, + "origin": "morph-explorer-input-src-bece7172-oz-v5.1.0", + "strippedSha256": "c65c6dcf454964007e86648e08ee776371297fa604e88fdc17e940f809536a5e", + "submoduleOverrides": [ + { + "path": "lib/openzeppelin-contracts", + "ref": "69c8def5f222ff96f2b5beff05dfba996368aa79" + } + ] + }, + "profile": { + "context": "explorer-settings", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "hint+native", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3872, + "origin": "hint+native", + "strippedSha256": "4bdd5d473028a3dc1c724eec0c1c60f2dc20e0d341f25dce5267305934d39e85" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23365, + "origin": "hint+native", + "strippedSha256": "408124d9963c57097485489405479fd6df2a8e413f32e31492eb1dd5e8895aa6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2534, + "origin": "hint+native", + "strippedSha256": "f98bd760c3818f32272f4c5bc9485b83d34e9a557d0443dca200e52eb2cdadaa" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3599, + "origin": "hint+native", + "strippedSha256": "83e2e2c4d440ed1073480505822963a4600d98c878a9b65cf90a81ecdd9984bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9419, + "origin": "hint+native", + "strippedSha256": "42c58b74bd40be0268f5ea0b37691df2a74b60d9ac3124a2148a08ad7d4c9eb4" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "7b2f05f8f2fc093f679463209dea202e9af3b120", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22086, + "origin": "morph-explorer-input-matches-origin/deployment-morph-tip", + "strippedSha256": "58879ebab6910635dbdf1344ccc04cab815b8a26cb23502ba8e1b387a96ede7c" + }, + "profile": { + "context": "explorer-settings", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "96b83f80ded9ac3f28bfce871b55917e360b9159", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "gitlink-bump", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "hint+native", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "hint+native", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "hint+native", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "eae25d382bb58aaaaa9f1a3a55567af993ce32be", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 3882, + "origin": "hist+native", + "strippedSha256": "9469decdb8d2280ac3dee6e320c52d16bcd164d10bf25d0add3000bd5be673b7" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "42161": { + "EUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 11981, + "origin": "ovr:dc3be15-v5.1.0", + "strippedSha256": "47294620c90c9199e0f7a39434092ca19f03307bc7b3e28dd32f37d839ae16db", + "submoduleOverrides": [ + { + "path": "lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/openzeppelin-contracts", + "ref": "v5.1.0" + } + ] + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 100000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+explorer", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+explorer", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12615, + "origin": "hint+native", + "strippedSha256": "1036d1c0fbc36f8f16e64f9c1d9afdad98eab38cb9a0d678ebc1abcbe11f4baa" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24408, + "origin": "hint+explorer", + "strippedSha256": "c9ee150eb7d0223886b2ba10217238e3947c9bdef1cbe97ba978e6ebf77355c3" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "hint+explorer", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Factory": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 8305, + "origin": "hint+native", + "strippedSha256": "7c9a247e972a8a3c9fcdeacc4716b1614d613dc969016a2bae4e142396e082bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Implementation": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 24313, + "origin": "hint+native", + "strippedSha256": "20cae9a429cf62fe9cbbc90acc8fa4529a2e08f8ff0b9c34413015bdd9215ce6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Periphery": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2422, + "origin": "hint+native", + "strippedSha256": "703cfc72cd6c5fcfe53371822c5670cc72bce7aa91a5976ee254292b5e3f3b24" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3872, + "origin": "hint+native", + "strippedSha256": "4bdd5d473028a3dc1c724eec0c1c60f2dc20e0d341f25dce5267305934d39e85" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23365, + "origin": "hint+native", + "strippedSha256": "408124d9963c57097485489405479fd6df2a8e413f32e31492eb1dd5e8895aa6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2534, + "origin": "hint+native", + "strippedSha256": "f98bd760c3818f32272f4c5bc9485b83d34e9a557d0443dca200e52eb2cdadaa" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3599, + "origin": "hint+native", + "strippedSha256": "83e2e2c4d440ed1073480505822963a4600d98c878a9b65cf90a81ecdd9984bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9419, + "origin": "hint+native", + "strippedSha256": "42c58b74bd40be0268f5ea0b37691df2a74b60d9ac3124a2148a08ad7d4c9eb4" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "a7d3c29ef7e4964736e47675e0588630d6afbfd7", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22050, + "origin": "hint+explorer", + "strippedSha256": "b12f6d72b8c5547a8a77595732e64e7b3e7f432357252ce4b13015605877c936" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "96b83f80ded9ac3f28bfce871b55917e360b9159", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "gitlink-bump", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "hint+explorer", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "hint+native", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "hint+explorer", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 5586, + "origin": "hint+native", + "strippedSha256": "2fc2cdd1b6e45a1d03326395d392a7418aa02fd05c71dbf5d845bcc7154354eb" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "43114": { + "EUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 11981, + "origin": "ovr:dc3be15-v5.1.0", + "strippedSha256": "47294620c90c9199e0f7a39434092ca19f03307bc7b3e28dd32f37d839ae16db", + "submoduleOverrides": [ + { + "path": "lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/openzeppelin-contracts", + "ref": "v5.1.0" + } + ] + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 100000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+era", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+era", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12615, + "origin": "hint+native", + "strippedSha256": "1036d1c0fbc36f8f16e64f9c1d9afdad98eab38cb9a0d678ebc1abcbe11f4baa" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24408, + "origin": "hint+native", + "strippedSha256": "c9ee150eb7d0223886b2ba10217238e3947c9bdef1cbe97ba978e6ebf77355c3" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "hint+native", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Factory": { + "commit": "c7da2f330dff3efb98b0b4e998f9b9f498b37c30", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 8327, + "origin": "avax-fix-solmate-remapping", + "strippedSha256": "f165204974081f9b04925ef7b664f5cd7006624813d3413ddcae4311e54b0d74" + }, + "profile": { + "context": "euler-swap", + "evm_version": "shanghai", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Implementation": { + "commit": "c7da2f330dff3efb98b0b4e998f9b9f498b37c30", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 24332, + "origin": "avax-fix-solmate-remapping", + "strippedSha256": "222485e60ee4ebd2ea6f886359d760a4c95c5c006d82b7248588c32c449f2d56" + }, + "profile": { + "context": "euler-swap", + "evm_version": "shanghai", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Periphery": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2422, + "origin": "hint+native", + "strippedSha256": "703cfc72cd6c5fcfe53371822c5670cc72bce7aa91a5976ee254292b5e3f3b24" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3872, + "origin": "hint+native", + "strippedSha256": "4bdd5d473028a3dc1c724eec0c1c60f2dc20e0d341f25dce5267305934d39e85" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23365, + "origin": "hint+native", + "strippedSha256": "408124d9963c57097485489405479fd6df2a8e413f32e31492eb1dd5e8895aa6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2534, + "origin": "hint+native", + "strippedSha256": "f98bd760c3818f32272f4c5bc9485b83d34e9a557d0443dca200e52eb2cdadaa" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3599, + "origin": "hint+native", + "strippedSha256": "83e2e2c4d440ed1073480505822963a4600d98c878a9b65cf90a81ecdd9984bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9419, + "origin": "hint+native", + "strippedSha256": "42c58b74bd40be0268f5ea0b37691df2a74b60d9ac3124a2148a08ad7d4c9eb4" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "a7d3c29ef7e4964736e47675e0588630d6afbfd7", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22050, + "origin": "hint+explorer", + "strippedSha256": "b12f6d72b8c5547a8a77595732e64e7b3e7f432357252ce4b13015605877c936" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "96b83f80ded9ac3f28bfce871b55917e360b9159", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "gitlink-bump", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "hint+native", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "hint+native", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "hint+native", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 5586, + "origin": "hint+native", + "strippedSha256": "2fc2cdd1b6e45a1d03326395d392a7418aa02fd05c71dbf5d845bcc7154354eb" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "56": { + "EUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 11981, + "origin": "ovr:dc3be15-v5.1.0", + "strippedSha256": "47294620c90c9199e0f7a39434092ca19f03307bc7b3e28dd32f37d839ae16db", + "submoduleOverrides": [ + { + "path": "lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/openzeppelin-contracts", + "ref": "v5.1.0" + } + ] + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 100000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+explorer", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+explorer", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12615, + "origin": "hint+native", + "strippedSha256": "1036d1c0fbc36f8f16e64f9c1d9afdad98eab38cb9a0d678ebc1abcbe11f4baa" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24408, + "origin": "hint+explorer", + "strippedSha256": "c9ee150eb7d0223886b2ba10217238e3947c9bdef1cbe97ba978e6ebf77355c3" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "hint+explorer", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Factory": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 8305, + "origin": "hint+native", + "strippedSha256": "7c9a247e972a8a3c9fcdeacc4716b1614d613dc969016a2bae4e142396e082bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Implementation": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 24313, + "origin": "hint+native", + "strippedSha256": "20cae9a429cf62fe9cbbc90acc8fa4529a2e08f8ff0b9c34413015bdd9215ce6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Periphery": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2422, + "origin": "hint+native", + "strippedSha256": "703cfc72cd6c5fcfe53371822c5670cc72bce7aa91a5976ee254292b5e3f3b24" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3872, + "origin": "hint+native", + "strippedSha256": "4bdd5d473028a3dc1c724eec0c1c60f2dc20e0d341f25dce5267305934d39e85" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23365, + "origin": "hint+native", + "strippedSha256": "408124d9963c57097485489405479fd6df2a8e413f32e31492eb1dd5e8895aa6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2534, + "origin": "hint+native", + "strippedSha256": "f98bd760c3818f32272f4c5bc9485b83d34e9a557d0443dca200e52eb2cdadaa" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3599, + "origin": "hint+native", + "strippedSha256": "83e2e2c4d440ed1073480505822963a4600d98c878a9b65cf90a81ecdd9984bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9419, + "origin": "hint+native", + "strippedSha256": "42c58b74bd40be0268f5ea0b37691df2a74b60d9ac3124a2148a08ad7d4c9eb4" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "a7d3c29ef7e4964736e47675e0588630d6afbfd7", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22050, + "origin": "hint+explorer", + "strippedSha256": "b12f6d72b8c5547a8a77595732e64e7b3e7f432357252ce4b13015605877c936" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "96b83f80ded9ac3f28bfce871b55917e360b9159", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "gitlink-bump", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "hint+explorer", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "hint+native", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "hint+explorer", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 5586, + "origin": "pool(n=9)", + "strippedSha256": "2fc2cdd1b6e45a1d03326395d392a7418aa02fd05c71dbf5d845bcc7154354eb" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "59144": { + "EUL": { + "commit": "21a169d7830f71fcfbee6f7ced12bf089f4fba20", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7920, + "origin": "sibling", + "strippedSha256": "d6078fb22fa20b31c9375da81084e5e122563556cb846ac26158a6f32620255d" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "london", + "optimizer_runs": 10000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 11053, + "origin": "linea-explorer-input-deps-from-evk-periphery-edaf96e3-workspace", + "strippedSha256": "8a4340d846344094b9311f1deba04b5c73624a0630e182b579fcf96e5d0d3252", + "submoduleOverrides": [ + { + "path": "lib/ethereum-vault-connector", + "ref": "b9d557a8ebcd3db1fbeef4aa60282aa4059a7bbf" + }, + { + "path": "lib/openzeppelin-contracts", + "ref": "69c8def5f222ff96f2b5beff05dfba996368aa79" + } + ] + }, + "profile": { + "context": "explorer-settings", + "evm_version": "london", + "optimizer_runs": 10000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5740, + "origin": "hint+explorer", + "strippedSha256": "57b0108017b4b57583f5d13b8dd9562d953b8b1ce592329f88e9d93ed98ed463" + }, + "profile": { + "context": "native", + "evm_version": "london", + "optimizer_runs": 10000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 21328, + "origin": "hint+explorer", + "strippedSha256": "86133ece4a9139f6f91a43167f110f1cb6f49bcfbfb7deed7ee80a6dc8639b51" + }, + "profile": { + "context": "native", + "evm_version": "london", + "optimizer_runs": 10000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "21a169d7830f71fcfbee6f7ced12bf089f4fba20", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12696, + "origin": "deployment-linea", + "strippedSha256": "ee5f56610126fce27b460a3bb97c16b3280bac45fcc22aaca989765029df4862" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "london", + "optimizer_runs": 10000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "ba581a71245ad004d35241918946b08ba63552cd", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24038, + "origin": "deployment-linea-reconstructed+london", + "strippedSha256": "978dba086e9345e9ef0290495242cff08456d4b0ad52076195b0b673a41bfb3a" + }, + "profile": { + "context": "euler-earn", + "evm_version": "london", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5337, + "origin": "hint+explorer", + "strippedSha256": "055f4a97a877bf3a28e0929c84be43ec2f7440ff84304779d5b87f819050d860" + }, + "profile": { + "context": "native", + "evm_version": "london", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Factory": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 7817, + "origin": "linea-workspace-oz510", + "strippedSha256": "733771fc71b8cadcc00bc5513c1e75b8726853be7f296894fc6b1733e7c2c082", + "submoduleOverrides": [ + { + "path": "lib/openzeppelin-contracts", + "ref": "69c8def5f222ff96f2b5beff05dfba996368aa79" + } + ] + }, + "profile": { + "context": "euler-swap", + "evm_version": "london", + "optimizer_runs": 10000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Implementation": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23166, + "origin": "linea-workspace-oz510", + "strippedSha256": "85a323795e717a5906347400be8899e27fa4c0ab7b04fc0cc49b5bd4ebbd7ea5", + "submoduleOverrides": [ + { + "path": "lib/openzeppelin-contracts", + "ref": "69c8def5f222ff96f2b5beff05dfba996368aa79" + } + ] + }, + "profile": { + "context": "euler-swap", + "evm_version": "london", + "optimizer_runs": 10000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Periphery": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2472, + "origin": "linea-workspace-oz510", + "strippedSha256": "9b00707ebcd7039ada1e50c131e632a3e6a7f63cd9bf7375e51d7a0e14a1e0c7", + "submoduleOverrides": [ + { + "path": "lib/openzeppelin-contracts", + "ref": "69c8def5f222ff96f2b5beff05dfba996368aa79" + } + ] + }, + "profile": { + "context": "euler-swap", + "evm_version": "london", + "optimizer_runs": 10000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3975, + "origin": "linea-workspace-oz510", + "strippedSha256": "0a646505ce6c4b4dbf511f4cfe6e374c7b3661373fc3507a2251d942a73425f0", + "submoduleOverrides": [ + { + "path": "lib/openzeppelin-contracts", + "ref": "69c8def5f222ff96f2b5beff05dfba996368aa79" + } + ] + }, + "profile": { + "context": "euler-swap", + "evm_version": "london", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23854, + "origin": "linea-workspace-oz510", + "strippedSha256": "06ec2a313646e3da14651903d31f2bfd11aa47c04de4299c7ac077c42a120529", + "submoduleOverrides": [ + { + "path": "lib/openzeppelin-contracts", + "ref": "69c8def5f222ff96f2b5beff05dfba996368aa79" + } + ] + }, + "profile": { + "context": "euler-swap", + "evm_version": "london", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2591, + "origin": "linea-workspace-oz510", + "strippedSha256": "69ef138e27b659cf40dc93b424b75bcfd17615984c03192d0fe209bd96356b71", + "submoduleOverrides": [ + { + "path": "lib/openzeppelin-contracts", + "ref": "69c8def5f222ff96f2b5beff05dfba996368aa79" + } + ] + }, + "profile": { + "context": "euler-swap", + "evm_version": "london", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3647, + "origin": "linea-workspace-oz510", + "strippedSha256": "e85194c7aa3ca0c668e0a5649b1cf02506a9af389a43106c06fd161633985895", + "submoduleOverrides": [ + { + "path": "lib/openzeppelin-contracts", + "ref": "69c8def5f222ff96f2b5beff05dfba996368aa79" + } + ] + }, + "profile": { + "context": "euler-swap", + "evm_version": "london", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9684, + "origin": "linea-workspace-oz510", + "strippedSha256": "507db7026ac86379bde411ec44e37f2d4091a7e12dc9d4377ff7308578820e8f", + "submoduleOverrides": [ + { + "path": "lib/openzeppelin-contracts", + "ref": "69c8def5f222ff96f2b5beff05dfba996368aa79" + } + ] + }, + "profile": { + "context": "euler-swap", + "evm_version": "london", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "a7d3c29ef7e4964736e47675e0588630d6afbfd7", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 21251, + "origin": "hint+explorer", + "strippedSha256": "d1bce236afcafd937b3a2b18363f41c46e9be0c545d7d0b4cef42a19cf1f0e3f" + }, + "profile": { + "context": "native", + "evm_version": "london", + "optimizer_runs": 10000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "21a169d7830f71fcfbee6f7ced12bf089f4fba20", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6942, + "origin": "branch:origin/deployment-linea", + "strippedSha256": "dd195cf06e17d6f9de68ceccd3a607e79d65eb037cc6894522dcfa962d8592d3" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "london", + "optimizer_runs": 10000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3990, + "origin": "hint+explorer", + "strippedSha256": "ae8cce18e7b6f527333d2a9920ad78eabbedb3d788960a3f091a3615c1213f30" + }, + "profile": { + "context": "native", + "evm_version": "london", + "optimizer_runs": 10000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "21a169d7830f71fcfbee6f7ced12bf089f4fba20", + "contractName": "RewardToken", + "evidence": { + "codeSize": 9866, + "origin": "deployment-linea", + "strippedSha256": "2068798e559db28152cd9fc9309ed975b9007eb82cf82f3185c1d8103f7a0e89" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "london", + "optimizer_runs": 10000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 893, + "origin": "hint+explorer", + "strippedSha256": "f8601f0f66ffbf0091022b7221611e59a747d2ffdde4c1f651fec2db4bebf73f" + }, + "profile": { + "context": "native", + "evm_version": "london", + "optimizer_runs": 10000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "e7337a33cb2339de7bf19d41a765c426cfe71be2", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 5693, + "origin": "linea-explorer-input-reconstructed-settings-on-edaf96e3", + "strippedSha256": "696584513d591e3f2db7db7f42c91bd08a1ed8a7b8f3b71a31f43e75603c3e0f" + }, + "profile": { + "context": "explorer-settings", + "evm_version": "london", + "optimizer_runs": 10000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "60808": { + "EUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 11981, + "origin": "ovr:dc3be15-v5.1.0", + "strippedSha256": "47294620c90c9199e0f7a39434092ca19f03307bc7b3e28dd32f37d839ae16db", + "submoduleOverrides": [ + { + "path": "lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/openzeppelin-contracts", + "ref": "v5.1.0" + } + ] + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 100000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+era", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+era", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12615, + "origin": "hint+native", + "strippedSha256": "1036d1c0fbc36f8f16e64f9c1d9afdad98eab38cb9a0d678ebc1abcbe11f4baa" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "773453b1f4a6f1d27a1cd0c6d8f6ada572503b23", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24408, + "origin": "hint+native", + "strippedSha256": "c9ee150eb7d0223886b2ba10217238e3947c9bdef1cbe97ba978e6ebf77355c3" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "hint+native", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Factory": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 8305, + "origin": "hint+native", + "strippedSha256": "7c9a247e972a8a3c9fcdeacc4716b1614d613dc969016a2bae4e142396e082bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Implementation": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 24313, + "origin": "hint+native", + "strippedSha256": "20cae9a429cf62fe9cbbc90acc8fa4529a2e08f8ff0b9c34413015bdd9215ce6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Periphery": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2422, + "origin": "hint+native", + "strippedSha256": "703cfc72cd6c5fcfe53371822c5670cc72bce7aa91a5976ee254292b5e3f3b24" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3872, + "origin": "hint+native", + "strippedSha256": "4bdd5d473028a3dc1c724eec0c1c60f2dc20e0d341f25dce5267305934d39e85" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23365, + "origin": "hint+native", + "strippedSha256": "408124d9963c57097485489405479fd6df2a8e413f32e31492eb1dd5e8895aa6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2534, + "origin": "hint+native", + "strippedSha256": "f98bd760c3818f32272f4c5bc9485b83d34e9a557d0443dca200e52eb2cdadaa" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3599, + "origin": "hint+native", + "strippedSha256": "83e2e2c4d440ed1073480505822963a4600d98c878a9b65cf90a81ecdd9984bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9419, + "origin": "hint+native", + "strippedSha256": "42c58b74bd40be0268f5ea0b37691df2a74b60d9ac3124a2148a08ad7d4c9eb4" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "a7d3c29ef7e4964736e47675e0588630d6afbfd7", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22050, + "origin": "hint+era", + "strippedSha256": "b12f6d72b8c5547a8a77595732e64e7b3e7f432357252ce4b13015605877c936" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "sibling-proven", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4", + "submoduleOverrides": [ + { + "path": "lib/euler-price-oracle/lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/euler-price-oracle/lib/forge-std", + "ref": "v1.9.4" + } + ] + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "hint+native", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "hint+native", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "hint+native", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 5586, + "origin": "hint+native", + "strippedSha256": "2fc2cdd1b6e45a1d03326395d392a7418aa02fd05c71dbf5d845bcc7154354eb" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "80094": { + "EUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 11981, + "origin": "ovr:dc3be15-v5.1.0", + "strippedSha256": "47294620c90c9199e0f7a39434092ca19f03307bc7b3e28dd32f37d839ae16db", + "submoduleOverrides": [ + { + "path": "lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/openzeppelin-contracts", + "ref": "v5.1.0" + } + ] + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 100000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+explorer", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+explorer", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12615, + "origin": "hint+native", + "strippedSha256": "1036d1c0fbc36f8f16e64f9c1d9afdad98eab38cb9a0d678ebc1abcbe11f4baa" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "773453b1f4a6f1d27a1cd0c6d8f6ada572503b23", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24408, + "origin": "hint+explorer", + "strippedSha256": "c9ee150eb7d0223886b2ba10217238e3947c9bdef1cbe97ba978e6ebf77355c3" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "hint+explorer", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Factory": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 8305, + "origin": "hint+native", + "strippedSha256": "7c9a247e972a8a3c9fcdeacc4716b1614d613dc969016a2bae4e142396e082bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Implementation": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 24313, + "origin": "hint+native", + "strippedSha256": "20cae9a429cf62fe9cbbc90acc8fa4529a2e08f8ff0b9c34413015bdd9215ce6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Periphery": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2422, + "origin": "hint+native", + "strippedSha256": "703cfc72cd6c5fcfe53371822c5670cc72bce7aa91a5976ee254292b5e3f3b24" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3872, + "origin": "hint+native", + "strippedSha256": "4bdd5d473028a3dc1c724eec0c1c60f2dc20e0d341f25dce5267305934d39e85" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23365, + "origin": "hint+native", + "strippedSha256": "408124d9963c57097485489405479fd6df2a8e413f32e31492eb1dd5e8895aa6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2534, + "origin": "hint+native", + "strippedSha256": "f98bd760c3818f32272f4c5bc9485b83d34e9a557d0443dca200e52eb2cdadaa" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3599, + "origin": "hint+native", + "strippedSha256": "83e2e2c4d440ed1073480505822963a4600d98c878a9b65cf90a81ecdd9984bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9419, + "origin": "hint+native", + "strippedSha256": "42c58b74bd40be0268f5ea0b37691df2a74b60d9ac3124a2148a08ad7d4c9eb4" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "a7d3c29ef7e4964736e47675e0588630d6afbfd7", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22050, + "origin": "hint+explorer", + "strippedSha256": "b12f6d72b8c5547a8a77595732e64e7b3e7f432357252ce4b13015605877c936" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "sibling-proven", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4", + "submoduleOverrides": [ + { + "path": "lib/euler-price-oracle/lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/euler-price-oracle/lib/forge-std", + "ref": "v1.9.4" + } + ] + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "hint+explorer", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "hint+native", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "hint+explorer", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 5586, + "origin": "hint+native", + "strippedSha256": "2fc2cdd1b6e45a1d03326395d392a7418aa02fd05c71dbf5d845bcc7154354eb" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "8453": { + "EUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 12330, + "origin": "hint+explorer", + "strippedSha256": "48762e01048ffb0f0ecdbe25a09b46310fa8252a9b7eaaad17e002ca62dbb6d8" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+explorer", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+explorer", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12615, + "origin": "hint+native", + "strippedSha256": "1036d1c0fbc36f8f16e64f9c1d9afdad98eab38cb9a0d678ebc1abcbe11f4baa" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24408, + "origin": "hint+explorer", + "strippedSha256": "c9ee150eb7d0223886b2ba10217238e3947c9bdef1cbe97ba978e6ebf77355c3" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "hint+explorer", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Factory": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 8305, + "origin": "hint+native", + "strippedSha256": "7c9a247e972a8a3c9fcdeacc4716b1614d613dc969016a2bae4e142396e082bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Implementation": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 24313, + "origin": "hint+native", + "strippedSha256": "20cae9a429cf62fe9cbbc90acc8fa4529a2e08f8ff0b9c34413015bdd9215ce6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Periphery": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2422, + "origin": "hint+native", + "strippedSha256": "703cfc72cd6c5fcfe53371822c5670cc72bce7aa91a5976ee254292b5e3f3b24" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3872, + "origin": "hint+native", + "strippedSha256": "4bdd5d473028a3dc1c724eec0c1c60f2dc20e0d341f25dce5267305934d39e85" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23365, + "origin": "hint+native", + "strippedSha256": "408124d9963c57097485489405479fd6df2a8e413f32e31492eb1dd5e8895aa6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2534, + "origin": "hint+native", + "strippedSha256": "f98bd760c3818f32272f4c5bc9485b83d34e9a557d0443dca200e52eb2cdadaa" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3599, + "origin": "hint+native", + "strippedSha256": "83e2e2c4d440ed1073480505822963a4600d98c878a9b65cf90a81ecdd9984bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9419, + "origin": "hint+native", + "strippedSha256": "42c58b74bd40be0268f5ea0b37691df2a74b60d9ac3124a2148a08ad7d4c9eb4" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "a7d3c29ef7e4964736e47675e0588630d6afbfd7", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22050, + "origin": "hint+explorer", + "strippedSha256": "b12f6d72b8c5547a8a77595732e64e7b3e7f432357252ce4b13015605877c936" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "96b83f80ded9ac3f28bfce871b55917e360b9159", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "gitlink-bump", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "hint+explorer", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "hint+native", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "hint+explorer", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 5586, + "origin": "pool(n=9)", + "strippedSha256": "2fc2cdd1b6e45a1d03326395d392a7418aa02fd05c71dbf5d845bcc7154354eb" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "9745": { + "EUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 11981, + "origin": "ovr:dc3be15-v5.1.0", + "strippedSha256": "47294620c90c9199e0f7a39434092ca19f03307bc7b3e28dd32f37d839ae16db", + "submoduleOverrides": [ + { + "path": "lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/openzeppelin-contracts", + "ref": "v5.1.0" + } + ] + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 100000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "hint+explorer", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "hint+explorer", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12615, + "origin": "pool(n=12)", + "strippedSha256": "1036d1c0fbc36f8f16e64f9c1d9afdad98eab38cb9a0d678ebc1abcbe11f4baa" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24408, + "origin": "pool(n=4)", + "strippedSha256": "c9ee150eb7d0223886b2ba10217238e3947c9bdef1cbe97ba978e6ebf77355c3" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "pool(n=6)", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Factory": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 8305, + "origin": "pool(n=10)", + "strippedSha256": "7c9a247e972a8a3c9fcdeacc4716b1614d613dc969016a2bae4e142396e082bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Implementation": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 24313, + "origin": "pool(n=10)", + "strippedSha256": "20cae9a429cf62fe9cbbc90acc8fa4529a2e08f8ff0b9c34413015bdd9215ce6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV1Periphery": { + "commit": "b948f4052d7ab3116235ec754368b7125dbd5082", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2422, + "origin": "pool(n=11)", + "strippedSha256": "703cfc72cd6c5fcfe53371822c5670cc72bce7aa91a5976ee254292b5e3f3b24" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 1000000, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3872, + "origin": "pool(n=12)", + "strippedSha256": "4bdd5d473028a3dc1c724eec0c1c60f2dc20e0d341f25dce5267305934d39e85" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23365, + "origin": "pool(n=12)", + "strippedSha256": "408124d9963c57097485489405479fd6df2a8e413f32e31492eb1dd5e8895aa6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2534, + "origin": "pool(n=12)", + "strippedSha256": "f98bd760c3818f32272f4c5bc9485b83d34e9a557d0443dca200e52eb2cdadaa" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3599, + "origin": "pool(n=12)", + "strippedSha256": "83e2e2c4d440ed1073480505822963a4600d98c878a9b65cf90a81ecdd9984bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9419, + "origin": "pool(n=12)", + "strippedSha256": "42c58b74bd40be0268f5ea0b37691df2a74b60d9ac3124a2148a08ad7d4c9eb4" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "a7d3c29ef7e4964736e47675e0588630d6afbfd7", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22050, + "origin": "hint+explorer", + "strippedSha256": "b12f6d72b8c5547a8a77595732e64e7b3e7f432357252ce4b13015605877c936" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "ovr:epo-dc3be15-v1.9.4", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4", + "submoduleOverrides": [ + { + "path": "lib/euler-price-oracle/lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/euler-price-oracle/lib/forge-std", + "ref": "v1.9.4" + } + ] + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "pool(n=7)", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "pool(n=12)", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "pool(n=7)", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 5586, + "origin": "pool(n=9)", + "strippedSha256": "2fc2cdd1b6e45a1d03326395d392a7418aa02fd05c71dbf5d845bcc7154354eb" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + }, + "999": { + "EUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "ERC20BurnableMintable", + "evidence": { + "codeSize": 7768, + "origin": "sibling", + "strippedSha256": "0b021e3f1f7f0d3d62c9b7c3c0820ebd29075123385c09b27e57327a09486e1b" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "balanceTracker": { + "commit": "9eb7b8a7fa31c275d688063c4abd07165b50b89f", + "contractName": "TrackingRewardStreams", + "evidence": { + "codeSize": 11981, + "origin": "ovr:dc3be15-v5.1.0", + "strippedSha256": "47294620c90c9199e0f7a39434092ca19f03307bc7b3e28dd32f37d839ae16db", + "submoduleOverrides": [ + { + "path": "lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/openzeppelin-contracts", + "ref": "v5.1.0" + } + ] + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 100000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/reward-streams", + "verified": "bytecode", + "waiver": null + }, + "eVaultFactory": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "GenericFactory", + "evidence": { + "codeSize": 5631, + "origin": "pool(n=14)", + "strippedSha256": "3971bde2116cbb49dd941ad5f892a32aea759ea73ac4aa6e1e680e356c517e4e" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eVaultImplementation": { + "commit": "422bf2447047d32aa9f4e5bab4be16ab3ea67ec2", + "contractName": "EVault", + "evidence": { + "codeSize": 23147, + "origin": "pool(n=13)", + "strippedSha256": "8c0012726d857229772babd3ecfc138d6084183ee5d5e133d50e80f22fc799d9" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "eulOFTAdapter": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "MintBurnOFTAdapter", + "evidence": { + "codeSize": 12615, + "origin": "pool(n=12)", + "strippedSha256": "1036d1c0fbc36f8f16e64f9c1d9afdad98eab38cb9a0d678ebc1abcbe11f4baa" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnFactory": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "EulerEarnFactory", + "evidence": { + "codeSize": 24408, + "origin": "pool(n=4)", + "strippedSha256": "c9ee150eb7d0223886b2ba10217238e3947c9bdef1cbe97ba978e6ebf77355c3" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerEarnPublicAllocator": { + "commit": "b2fd6e699ee20bcfe7459f375b3cee5d2fa53345", + "contractName": "PublicAllocator", + "evidence": { + "codeSize": 5168, + "origin": "pool(n=6)", + "strippedSha256": "a6bee3db1d4b49237f0c9b53d2ffd95365ee9e8c77222d56665a6e25491ae314" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 200, + "solc": "0.8.26" + }, + "repo": "euler-xyz/euler-earn", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Factory": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapFactory", + "evidence": { + "codeSize": 3872, + "origin": "pool(n=12)", + "strippedSha256": "4bdd5d473028a3dc1c724eec0c1c60f2dc20e0d341f25dce5267305934d39e85" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Implementation": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwap", + "evidence": { + "codeSize": 23365, + "origin": "pool(n=12)", + "strippedSha256": "408124d9963c57097485489405479fd6df2a8e413f32e31492eb1dd5e8895aa6" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Periphery": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapPeriphery", + "evidence": { + "codeSize": 2534, + "origin": "pool(n=12)", + "strippedSha256": "f98bd760c3818f32272f4c5bc9485b83d34e9a557d0443dca200e52eb2cdadaa" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2ProtocolFeeConfig": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapProtocolFeeConfig", + "evidence": { + "codeSize": 3599, + "origin": "pool(n=12)", + "strippedSha256": "83e2e2c4d440ed1073480505822963a4600d98c878a9b65cf90a81ecdd9984bf" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "eulerSwapV2Registry": { + "commit": "81cf6dc988468fd56f690e6bc0e338a5be02d034", + "contractName": "EulerSwapRegistry", + "evidence": { + "codeSize": 9419, + "origin": "pool(n=12)", + "strippedSha256": "42c58b74bd40be0268f5ea0b37691df2a74b60d9ac3124a2148a08ad7d4c9eb4" + }, + "profile": { + "context": "native", + "evm_version": "prague", + "optimizer_runs": 2500, + "solc": "0.8.27" + }, + "repo": "euler-xyz/euler-swap", + "verified": "bytecode", + "waiver": null + }, + "evc": { + "commit": "a7d3c29ef7e4964736e47675e0588630d6afbfd7", + "contractName": "EthereumVaultConnector", + "evidence": { + "codeSize": 22050, + "origin": "pool(n=11)", + "strippedSha256": "b12f6d72b8c5547a8a77595732e64e7b3e7f432357252ce4b13015605877c936" + }, + "profile": { + "context": "native", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/ethereum-vault-connector", + "verified": "bytecode", + "waiver": null + }, + "oracleRouterFactory": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "EulerRouterFactory", + "evidence": { + "codeSize": 6826, + "origin": "ovr:epo-dc3be15-v1.9.4", + "strippedSha256": "d788109458c7d53cc7fe7773944f9123db2444b9d5bd7d4bd3ee2c759739e4c4", + "submoduleOverrides": [ + { + "path": "lib/euler-price-oracle/lib/ethereum-vault-connector", + "ref": "dc3be15" + }, + { + "path": "lib/euler-price-oracle/lib/forge-std", + "ref": "v1.9.4" + } + ] + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "protocolConfig": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "ProtocolConfig", + "evidence": { + "codeSize": 3953, + "origin": "pool(n=7)", + "strippedSha256": "844a4ed8293ed243d58f7df3514f8aec50a39523b3ef733451bea057d68bd04d" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "rEUL": { + "commit": "392c7bd035c6fa1f50388fe4b3f3f3cd04df09d8", + "contractName": "RewardToken", + "evidence": { + "codeSize": 10735, + "origin": "pool(n=12)", + "strippedSha256": "ea6d1628f20671e71ebf387ba533b756f9b8b6fd3ad0f7535f129eaaa95b9d62" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + }, + "sequenceRegistry": { + "commit": "9e3c760e051f5d769f7c6edb9be30198a55117d4", + "contractName": "SequenceRegistry", + "evidence": { + "codeSize": 867, + "origin": "pool(n=7)", + "strippedSha256": "83359e0027ead6632fc814808fd8c8dfaa4e1538638a28047f85c043c76e3e85" + }, + "profile": { + "context": "native", + "evm_version": "shanghai", + "optimizer_runs": 20000, + "solc": "0.8.23" + }, + "repo": "euler-xyz/euler-vault-kit", + "verified": "bytecode", + "waiver": null + }, + "swapVerifier": { + "commit": "edaf96e32ebe6cb96ae30add934d74fa1d092ff6", + "contractName": "SwapVerifier", + "evidence": { + "codeSize": 5586, + "origin": "pool(n=9)", + "strippedSha256": "2fc2cdd1b6e45a1d03326395d392a7418aa02fd05c71dbf5d845bcc7154354eb" + }, + "profile": { + "context": "evk-periphery", + "evm_version": "cancun", + "optimizer_runs": 20000, + "solc": "0.8.24" + }, + "repo": "euler-xyz/evk-periphery", + "verified": "bytecode", + "waiver": null + } + } +}