- Total Prize Pool: $65,000 in USDC
- HM awards: up to $57,600 in USDC
- If no valid Highs or Mediums are found, the HM pool is $0
- QA awards: $2,400 in USDC
- Judge awards: $4,500 in USDC
- Scout awards: $500 USDC
- HM awards: up to $57,600 in USDC
- Read our guidelines for more details
- Starts March 18, 2026 20:00 UTC
- Ends March 27, 2026 20:00 UTC
- While this audit's code is not yet deployed, a variation of the live code rules will apply, where all submissions will be treated as sensitive:
- Submissions will be hidden from all wardens (SR and non-SR alike) by default, to ensure that no sensitive issues are erroneously shared.
- Once the initial triage process has been completed, we’ll make submissions visible to verified (KYC'ed) wardens only. PJQA will be open to verified wardens per the usual C4 process.
- A coded, runnable PoC is required for all High/Medium submissions to this audit.
- This repo includes a basic template to run the test suite.
- PoCs must use the test suite provided in this repo.
- Your submission will be marked as Insufficient if the POC is not runnable and working with the provided test suite.
- Exception: PoC is optional (though recommended) for wardens with signal ≥ 0.4.
- Judging phase risk adjustments (upgrades/downgrades):
- High- or Medium-risk submissions downgraded by the judge to Low-risk (QA) will be ineligible for awards.
- Upgrading a Low-risk finding from a QA report to a Medium- or High-risk finding is not supported.
- As such, wardens are encouraged to select the appropriate risk level carefully during the submission phase.
- Please note that the findings and audit report will remain private to the sponsor team only.
V12 is Zellic's in-house AI auditing tool. It is the only autonomous Solidity auditor that reliably finds Highs and Criticals. All issues found by V12 will be judged as out of scope and ineligible for awards.
V12 findings can be viewed here.
Anything included in this section is considered a publicly known issue and is therefore ineligible for awards.
- The auction contract is not designed to support non-canonical ERC20s such as:
- Fee on transfer tokens
- Rebasing tokens
- Non approve 0 tokens (e.g. BNB)
- Arbitrary deposits of auctioned assets to the auction contract during live auctions: the auction contract relies on balance reading to determine the available auctioned amount, but the amount approval to the CowSwap settlement contract is done at auction start (in performUpkeep). Therefore, if additional auctioned assets are deposited in the contract during an auction, those assets won’t be made available to the CowSwap solvers (only participants calling the bid function). This is acceptable since such deposits would not be performed by us and therefore be a net positive even if swapped at the lower end of the auction curve.
- Asynchronous order updates on the CowSwap API: since auctions are relayed off-chain to the CowSwap API through periodic updates of limit orders:
- Orders posted on the CowSwap order book will always have a higher price than the on-chain auction value (since the price decays per second). This may delay slightly the auction fills but this is an acceptable tradeoff as the on-chain price invariant can’t be broken.
- Concurrent participants (CowSwap solvers and independent bidders) will both affect auctioned asset balances on the contract. Therefore, when a non CowSwap solver bids on the auction, the limit order quantity becomes stale on the CowSwap orderbook until the next workflow run. This may lead to failed orders attempted by solvers trying to fill 100% of the order during that time window.
Payment Abstraction is a system of onchain smart contracts that aim to reduce payment friction for Chainlink services. The system is designed to (1) accept fees in various tokens across multiple blockchain networks, (2) consolidate fee tokens onto a single blockchain network via Chainlink CCIP, (3) convert fee tokens into LINK and (4) pass converted LINK into a dedicated contract for withdrawal by Chainlink Network service providers.
While Payment Abstraction V1 uses Uniswap V3 for executing fee-to-LINK conversions, V2 implements a permissionless dutch auction mechanism where any participant can bid on auctioned allowlisted assets.
The goal of Payment Abstraction V2 is to replace the current Payment Abstraction V1 system by:
- Implementing a permissionless dutch auction mechanism where any participant can bid on auctioned allowlisted assets. This model improves flexibility and resiliency by supporting multiple liquidity venues.
- Integrating with CowSwap to relay auctions to the protocol’s solvers to ensure sufficient participation.
- Building a backward and forward compatible solution allowing to integrate with multiple liquidity venues.
This project includes an Audit Catalyst prepared by Zellic. This is an essential read for accelerating your work as an auditor and using your time most effectively in contributing to the security of the project.
- Previous audits: N/A
- Documentation: https://github.com/code-423n4/2026-03-chainlink/blob/main/payment_abstraction_v2.pdf
- Website: https://chain.link/
- X/Twitter: https://x.com/chainlink
See scope.txt
See out_of_scope.txt
- Any vector that may break the systems' invariant (auction curve). No bid should ever result in higher slippage than the set threshold
- The auction contract will hold funds during auctions, which therefore represent value at risk
- Rounding operations
- Any vector that may block auction participation
- Are there any user provided inputs that could result in unexpected behaviors/fund loss?
- Are there any race conditions that could result in sustained DoS?
- Are access controls implemented effectively to prevent unauthorized operations?
| Role | Description | Granted To |
|---|---|---|
| DEFAULT_ADMIN_ROLE | Owner of the contracts. Manages roles, critical configurations and can emergency withdraw assets. | Timelock |
| PAUSER_ROLE | Pauses the contract when an emergency is detected. | Monitoring |
| UNPAUSER_ROLE | Unpauses the contract when an emergency is resolved. This is separate from the PAUSER_ROLE to decouple the role. | Timelock |
| SWAPPER_ROLE | Assigned to the GPV2CompatibleAuction contract, this role allows for pulling allowlisted assets from the FeeAggregator contract when starting an auction. | GPV2CompatibleAuction |
| ASSET_ADMIN_ROLE | Configures feeds, asset parameters, minimum bid value and asset out. | Timelock |
| PRICE_ADMIN_ROLE | Transmits Streams prices to the GPV2CompatibleAuction contract. | WorkflowRouter |
| AUCTION_WORKER_ROLE | Starts and expires auctions by calling performUpkeep on the GPV2CompatibleAuction contract. | WorkflowRouter |
| AUCTION_BIDDER_ROLE | Pushes solutions to the AuctionBidder’s bid function to solve live auctions. | WorkflowRouter |
| ORDER_MANAGER_ROLE | Invalidates orders on the GPv2Settlement contract. | WorkflowRouter |
| FORWARDER_ROLE | Transmits CRE workflow payloads to the WorkflowRouter’s onReport function. | CRE forwarder |
The codebase utilizes a foundry installation to compile the codebase and run tests. As such, foundry is expected to be installed and specifically at version v1.5.0.
- pnpm
- foundry
- Create an
.envfile, following the.env.example(some tests will fail without a configured mainnet RPC)
$ # The below command can be skipped if foundry has been installed at the appropriate version
$ pnpm foundry
$ # Install dependencies of the project
$ pnpm install
$ # Compile all contracts
$ forge buildRun all tests:
$ forge testEmployees of Chainlink and employees' family members are ineligible to participate in this audit.
Code4rena's rules cannot be overridden by the contents of this README. In case of doubt, please check with C4 staff.