Back to Blog 

In this article: you'll learn how Ethereum's set-code transaction works at the protocol level, the four attack surfaces it opened on May 7 2025, how it composes with ERC-4337 in ways most teams have not modeled, and the specific checks auditors now run on delegate contracts and on protocols that accept calls from EOAs.
Pectra activated on Ethereum mainnet on May 7, 2025, at 10:05:11 UTC. Within four weeks, Wintermute's research team reported that more than 97% of EIP-7702 delegations on mainnet pointed to copy-pasted sweeper contracts. By late August, a single user had lost $1.54 million in a 7702 batch-transaction phishing attack. Earlier that summer, another user lost roughly $146,000 to an Inferno Drainer variant that piggybacked on a legitimate delegator address.
The numbers are interesting, but the framing matters more. None of these incidents were bugs in EIP-7702 itself. They were the consequences of a protocol change that, in a single signature, lets an externally owned account become a smart contract. The wallet attack surface that had been stable for years moved overnight. For protocol engineers integrating with wallets, for delegate-contract authors, and for ERC-4337 bundler and paymaster operators, the auditor's checklist now has new items on it. This post walks through what changed at the spec level, what went wrong in production, and what we now check during engagements.
How EIP-7702 actually works
EIP-7702 introduces a new EIP-2718 transaction type,
SET_CODE_TX_TYPE = 0x04. The payload extends the EIP-4844 transaction format with one new field: an authorization_list of tuples, each shaped [chain_id, address, nonce, y_parity, r, s]. A null destination is invalid. An empty authorization_list is invalid.Each authorization tuple is a signature over
keccak256(MAGIC || rlp([chain_id, address, nonce])), where MAGIC = 0x05 acts as a domain separator. The recovered signer is the authority, the EOA whose code is about to be set. Two details matter here. First, the s value must be at most secp256k1n/2, per EIP-2, to prevent malleability. Second, and far more important, the signer of the authorization tuple does not have to be tx.origin. This is what enables sponsored transactions, and it is also what enables a wallet drainer to submit an authorization on behalf of a user who signed it five minutes earlier on a phishing site.
When a valid tuple is processed, the EVM sets the authority's code to a 23-byte sequence:
10xef0100 || address
This is the delegation designator. The
0xef prefix reuses the opcode that EIP-3541 banned as a contract-code prefix, marking this code as having a special meaning. From this point on, code-executing opcodes and direct transaction calls follow the pointer; code-reading opcodes do not. From the spec:| Opcode | Behavior against a delegated EOA |
|---|---|
CALL, CALLCODE, STATICCALL, DELEGATECALL | Loads implementation code from address and executes it in the authority's context. |
Transaction destination matching authority | Same as above. |
EXTCODESIZE | Returns 2 (the size of 0xef01). |
EXTCODECOPY | Operates on the first two bytes of the designator. |
EXTCODEHASH | Returns keccak256(0xef01). |
The asymmetry between execution and introspection is a deliberate design choice. The spec's "Delegation of code execution only" rationale argues that if
EXTCODEHASH followed the pointer too, an account could temporarily masquerade as having a particular codehash, which would break contracts that rely on codehashes as a behavioral fingerprint. The trade-off works at the protocol layer but creates several of the attack surfaces below.A delegation is persistent. It stays in effect across transactions until replaced by a new authorization tuple. To revoke, the EOA owner signs a tuple pointing to
address(0), which the spec handles as a special case: the code is cleared and the code hash is reset to the empty hash. To re-delegate, sign a tuple pointing to a different implementation.Gas costs are inherited from EIP-2930 plus
PER_EMPTY_ACCOUNT_COST × len(authorization_list), where PER_EMPTY_ACCOUNT_COST = 25000 and PER_AUTH_BASE_COST = 12500. The transaction sender pays for every tuple, valid or not. Cheap enough that attackers were willing to authorize tens of thousands of compromised EOAs to sweeper contracts at a marginal cost of cents per address.The four attack surfaces

Surface 1: phishing the authorization tuple
The first thing to internalize about EIP-7702 is that the signature is the deployment. There is no separate "send a transaction to the contract" step. A user who signs an authorization tuple has handed execution control of their EOA to the address in that tuple, period. The tuple itself carries only
(chain_id, target, [nonce](https://www.zealynx.io/glossary/nonce), y_parity, r, s). It encodes no execution scope, no call restriction, no expiry, no value cap. The user signing it cannot constrain what the delegate will do, because the delegate's logic is whatever code lives at target.In production, this has played out exactly as the threat model predicted.
On May 24, 2025, Scam Sniffer flagged a MetaMask user who lost approximately $146,551 to a malicious EIP-7702 batched transaction tied to Inferno Drainer. SlowMist's founder Yu Xian analyzed the attack and described the mechanism: the phishing site induced the user to sign what appeared to be a routine token swap. The signature actually authorized delegation to an attacker-controlled implementation and included a batch of token approvals and transfers in the same transaction. The user did not approve token transfers in the usual sense; they signed once and the entire batch executed atomically.
Three months later, on August 24, 2025, the same pattern produced a single-victim loss of $1.54 million in wstETH, cbBTC, and NFTs. Scam Sniffer's analysis described "multiple victims with this pattern targeting EIP-7702 upgraded addresses." The phishing surface had matured: drainer kits, including the Inferno Drainer Reloaded campaign tracked by Three Sigma, now bundle EIP-7702 delegation payloads into SET_CODE transaction templates with auto-generated calldata and simulation evasion built in.
Behind these individual losses sits the structural pattern Wintermute documented on May 30, 2025: when Wintermute's research team analyzed the first month of post-Pectra delegation data, they found that more than 97% of all EIP-7702 delegations on mainnet pointed to a small number of contract families running essentially identical sweeper bytecode. Wintermute decompiled the most reused variant, gave it the name "CrimeEnjoyor," and published it as verified Solidity with an explicit warning baked into the source. By June, two more families (CrimeEnjoyor2 and AdvancedCrimerEnjoyor) had been catalogued.
A clarifying note from Taylor Monahan that we agree with: in the sweeper case, the underlying root cause is leaked private keys. 7702 did not steal those keys. What 7702 did was make sweeping the address cheaper, faster, and more reliable than running a frontrunning bot on every incoming deposit. The 7702-specific attack is the phishing-signature pattern in the Inferno Drainer cases, not the sweeper-after-key-leak pattern. Both matter; they are different problems.
Surface 2: insecure delegate contracts
Even if the user signs in good faith and authorizes a contract they intended to authorize, a delegate with sloppy code is exploitable. This is where most of our audit work on 7702 actually lives. Nethermind's research team published a useful catalog of vulnerability classes on April 8, 2025, and the spec's own "Secure delegation" section enumerates four invariants that any delegate signature must cover.
The simplest failure is missing access control. Nethermind's canonical example:
1contract VulnerableContract {2 function doSomething(bytes memory _data, address _to, uint _value) public payable {3 (bool success, ) = _to.call{value: _value}(_data);4 require(success);5 }6}
Anyone who knows the address of an EOA delegated to this contract can call
doSomething with any _data, _to, and _value. The user did not authorize specific calls; they authorized this contract. If the contract does not authenticate every call, the delegation is a public power of attorney over the EOA's funds.The fix is exactly what the spec asks for, in plain language: the delegate must require a signature from the EOA's authority over each operation, and that signature must commit to a nonce (for replay protection), the
value, the gas limit, and the target plus calldata. Omit any of these and the delegate is exploitable. Without a nonce, signatures replay. Without value, a malicious sponsor can change how much ETH gets sent. Without gas, a malicious sponsor can starve the call. Without target/calldata, the sponsor can route the call anywhere. The spec puts it plainly: "a poorly implemented delegate can allow a malicious actor to take near complete control over a signer's EOA."A second class of failure is initialization handling. When an EOA delegates to a contract, that contract's
constructor does not run in the EOA's context. The delegation transaction does not include initcode. Smart-account designers used to proxy patterns will recognize the workaround: use an initialize function. But this creates a frontrunning window. If the user delegates in one transaction and calls initialize in another, an observer can call initialize first with parameters that hand control to themselves. The mitigation is to batch delegation and initialization in the same transaction, and to authenticate the initialize call against the EOA key via ecrecover so an unrelated party cannot call it.A third class is storage collision across redelegations. The delegation pointer can be replaced. The EOA's storage cannot. If a user delegates first to a contract whose slot 0 is a
bool and then to a contract whose slot 0 is a uint256, the second contract reads a corrupted value at slot 0. OpenZeppelin's Contracts 5.x documentation makes the recommendation explicit: any contract intended as a 7702 delegate should use ERC-7201 namespaced storage. The discipline is the same as for upgradeable proxies. Treat the EOA's storage as state that will outlive any single delegate.These are not exotic findings. They are the kinds of issues that show up in the first pass of any review of a delegate-contract codebase. The Nethermind post catalogs them as the minimum set developers should know before shipping. Our own checklist extends them with the items in the auditor's section below.
Surface 3: cross-chain replay via chain_id = 0

The EIP-7702 spec permits
chain_id = 0 in the authorization tuple. The Rationale section explains why: wallet vendors wanted to be able to ship a single signed authorization that delegates to the same proxy on every EVM chain, without forcing the user to sign a separate tuple per chain. The trade-off is documented and, as a feature, the protocol authors considered it acceptable.What the spec is more reserved about is the threat model. An academic analysis published on arxiv in December 2025 (
2512.12174) ran the obvious experiment: three independent Hardhat chains (chain IDs 1337, 2337, 3337), one identical malicious delegate deployed at the same address on each chain, one phishing victim signs one chain_id = 0 authorization tuple. The attacker submits the same tuple verbatim on all three chains. All three accept it. Each chain independently verifies the signature, confirms the nonce, writes the 0xef0100 || delegate designator, and increments the nonce.The compromise is not the same as classic replay attack. In classic replay, the attacker reuses the same transaction across networks. With a
chain_id = 0 tuple, the attacker can craft fresh transactions on any chain, all anchored in the one signature the victim ever produced. Nonce constraints offer no containment because each chain maintains its own EOA nonce independently. A single phishing event becomes a multi-domain takeover the moment the victim's EOA exists on a second EVM chain, which, for any retail user with assets on Optimism, Arbitrum, Base, or Polygon, is the default state of the world.Mitigations from SlowMist and the same arxiv paper are straightforward. Wallets should refuse to sign
chain_id = 0 authorizations by default; the cross-chain convenience is not worth the surface. Nodes can reject tuples where chain_id doesn't match the local chain, except when explicitly zero. Wallet UIs should preflight the declared chain against the connected network and surface a clear warning on mismatch. None of these are universally deployed yet.Surface 4: ERC-4337 as a remote activation vector
This is the surface most coverage misses, and it's the most interesting one for teams running ERC-4337 infrastructure.
EIP-7702 and ERC-4337 were intentionally designed to compose. The 7702 spec's "Forward-compatibility with future account abstraction" section says explicitly that 7702 "allows EOAs to masquerade as contracts to be included in ERC-4337 bundles, in a way that's compatible with the existing EntryPoint." The idea is good. A 7702-delegated EOA can be the smart account that a 4337 bundler routes through paymasters. Most reference architectures for hybrid account abstraction assume exactly this pattern.
The composition creates an attack surface that isn't visible from either spec alone. Once an EOA has been delegated to a malicious contract, any call to that EOA's address routes into the malicious code. That includes:
- User-driven calls: the victim sends ETH to their own address (a common pattern for force-sending gas or unsticking a nonce). The call dispatches into the delegate's fallback.
- Attacker-driven calls: the attacker sends a transaction directly to the victim's EOA. No further signature from the victim is required. The delegate's logic runs.
- Protocol-triggered calls: any router contract, paymaster pre-verification callback, or batched UserOperation that targets the victim's address activates the delegate.
The third pathway is the novel one. The arxiv paper documents a real on-chain transaction on PlasmaScan (
0x4a8fee...c14c3) which is a plain ERC-4337 handleOps call, not a typed 0x04 transaction, that routes execution into a delegated EOA. The callee is not a contract wallet; it's an EOA whose code begins with the 0xef0100 designator. The EntryPoint follows the designator, loads the delegate's code, and executes. The bundler is acting in good faith. The EntryPoint is acting per spec. The victim signed once, weeks earlier, on a phishing site.For bundler operators, this means
validateUserOp is no longer a pure validation step. If the callee is a delegated EOA pointing to attacker-controlled code, the validation runs that code. For paymaster designers, every paymaster verification callback that touches a counterparty address is a potential trigger. For protocol contracts that route UserOperations into wallet addresses, the threat model now includes the case where the wallet is an EOA whose execution semantics were replaced by a signature the wallet's "owner" had no idea they were giving.EIP-7702 versus ERC-4337, from a security standpoint

A short comparison, focused on the differences that change the threat model. This is not a "which is better" framing; both are infrastructure, both are here to stay, and both compose.
| Property | ERC-4337 (pre-Pectra) | EIP-7702 (Pectra-era) |
|---|---|---|
| Where it lives | Off-chain mempool plus on-chain EntryPoint | In-protocol, transaction type 0x04 |
| Account model | Smart-contract wallet at a new address | EOA keeps original address and private key |
| Activation cost | Contract deployment | One signature |
| Persistence | Permanent (contract deployment) | Persistent until revoked or replaced |
| Private-key compromise | Owner key loss compromises the smart wallet | Owner key loss compromises everything, plus 7702 makes draining cheaper |
| Address migration | Yes | No |
| Initialization | Runs constructor or initialize on deploy | No constructor; initialize must be separate and authenticated |
| Storage isolation | Per contract | EOA storage persists across re-delegations |
| Impact on existing contracts | Mostly contained; EXTCODESIZE > 0 is a clear signal | tx.origin == msg.sender and "is this an EOA" patterns become unreliable; EXTCODESIZE returns 2 for delegated EOAs |
| Cross-chain replay risk at the AA layer | None | chain_id = 0 enables multi-domain replay |
The honest framing: 4337 is infrastructure, 7702 is protocol, and they compose. But composition creates the EntryPoint-as-activation-vector class above, which is not visible from either spec read in isolation.
What auditors check now

The shift that matters: delegate contracts and wallet integrations are now in audit scope alongside the smart contracts they touch. The checks below are the ones we walk through on engagements that involve 7702.
If you are writing a delegate contract:
Are you audit-ready?
Download the free Pre-Audit Readiness Checklist used by 30+ protocols preparing for their first audit.
No spam. Unsubscribe anytime.
Every function callable on the delegated EOA must answer five questions before executing anything. Is the call authenticated against the EOA's key? Does the signature include a nonce that prevents replay? Is the value bounded? Is the gas bounded? Are the target and calldata included in what was signed? Miss any one of these and the spec's secure-delegation invariants are violated.
Storage must follow ERC-7201 namespaced layout. Assume the EOA will redelegate. A delegate that uses traditional sequential slot layout will collide with the next delegate the user picks. Don't trust that you'll be the last delegate in the chain.
No constructor logic. Use an
initialize function. Authenticate the initialize call against the EOA key via ecrecover, or batch delegation and initialization atomically in the same transaction. The unauthenticated variant is the frontrun bug that the spec's "Front running initialization" section warns about.Reject
chain_id = 0 authorizations unless the contract's behavior is genuinely identical across every EVM chain it might end up on. Cross-chain reuse of the same delegate address is fine; cross-chain reuse of the same signature is not.Be aware that any external call from the delegate originates as
tx.origin == msg.sender from the called contract's perspective. Don't rely on this invariant in your own delegate logic or in any contract you call.If you are writing a protocol contract that accepts calls from EOAs:
require(msg.sender == tx.origin) is no longer a topmost-frame check. The spec acknowledges this directly. If you used it for reentrancy protection, replace it with ReentrancyGuard or a transient-storage mutex. If you used it for atomic-sandwich protection, accept that the protection is gone for delegated EOAs. We covered the wider tx.origin phishing class earlier — EIP-7702 turns those classical anti-patterns into immediate risks for every protocol that still relies on them.If you genuinely need to detect a 7702-delegated caller, check the first three bytes of
msg.sender.code for the 0xef0100 prefix. Halborn published a clean implementation:1error DelegationNotAllowed();23modifier noEIP7702Delegation() {4 bytes memory code = msg.sender.code;5 if (code.length >= 3) {6 if (code[0] == bytes1(0xef) &&7 code[1] == bytes1(0x01) &&8 code[2] == bytes1(0x00)) {9 revert DelegationNotAllowed();10 }11 }12 _;13}
The check is cheap and unambiguous. Note that
EXTCODESIZE(account) returns 2 for a delegated EOA, 0 for a true EOA, and ≥ 23 for a regular contract. That's also enough to distinguish, but reading the prefix directly is more explicit.If your protocol's threat model assumes
msg.sender is either a known contract or a true EOA, you now have a third category to handle.If you are running ERC-4337 infrastructure:
Treat any UserOperation whose
sender has non-empty code beginning with 0xef0100 as a delegated EOA pointing to a delegate you have not vetted. validateUserOp against such a sender may execute attacker-controlled code during the validation step. Bundlers and paymasters that assume validation is a side-effect-free signature check are wrong in the presence of 7702-delegated victims.The defensive posture is to filter or flag UserOps whose callee carries the 7702 designator unless the delegate is explicitly trusted (the wallet vendor's own audited implementation, for example). This isn't perfect, since phishing victims are by definition holding malicious delegates, but it shifts the trust boundary back to the bundler operator's allowlist rather than the EntryPoint's permissive routing.
Where this leaves us
Pectra was the moment the wallet became a programmable contract for every Ethereum user, simultaneously, by default. The protocol is not at fault; the design is sound and the trade-offs in the spec are documented carefully. The fault, where there is one, is in the gap between the protocol's flexibility and the ecosystem's readiness to audit what now sits inside that flexibility.
For the year ahead, the delegate-contract layer is the part of the wallet stack with the highest density of unaudited code per dollar of TVL. Sweeper contracts will continue to find leaked private keys; phishing kits will continue to evolve their authorization-signing UIs; and ERC-4337 infrastructure will continue to compose with 7702 in ways that need explicit threat modeling rather than implicit trust.
Get in touch
EIP-7702 collapsed three security domains — wallet code, delegate contracts, and protocol-side EOA assumptions — into a single audit surface. Most teams shipping in 2026 are still scoping them as if they were separate problems. At Zealynx, we audit them as one.
Whether you're writing a delegate contract for a new wallet, integrating 7702 into an existing ERC-4337 stack, or hardening a protocol that accepts calls from EOAs in a post-Pectra world, we apply the same systematic methodology we use for upgradeable proxies and account abstraction reviews.
What we cover on a 7702 engagement:
- Delegate-contract audit — Per-call authentication, ERC-7201 storage discipline, initialization frontrun review, and
chain_id = 0posture - Protocol-side EOA assumption review — Replace
tx.originandEXTCODESIZE-based detection with 7702-safe primitives - ERC-4337 + 7702 composition review — Bundler and paymaster validation flows when the callee is a delegated EOA
- Wallet-vendor signing-UX review — How your wallet surfaces 7702 authorization signatures, and whether it refuses
chain_id = 0by default
FAQ: EIP-7702 wallet security and post-Pectra audits
1. What is an EOA, and what does EIP-7702 let one do that it could not do before?
An EOA (externally owned account) is the kind of Ethereum account that is controlled by a private key — what most people mean when they say "wallet address." Before EIP-7702, an EOA could only sign transactions; it could not execute smart contract code at its own address. EIP-7702 changes that: by signing one authorization tuple, the EOA owner can point the account's execution to any contract address, so that subsequent calls to the EOA run that contract's code in the EOA's storage and
msg.sender context. The EOA keeps its address, private key, and balance — but its execution semantics are now programmable. This is why EIP-7702 is sometimes called a bridge to account abstraction: a user can opt into smart-account behavior without migrating to a new contract address.2. What was the Pectra hard fork and why does May 7, 2025 matter for wallet security?
Pectra is the Ethereum hard fork that activated on mainnet on May 7, 2025, at 10:05:11 UTC. It combined the consensus-layer "Prague" upgrade with the execution-layer "Electra" upgrade, and bundled several EIPs — including EIP-7702. May 7, 2025 matters because it is the moment every EOA on Ethereum mainnet became capable of signing a delegation authorization, simultaneously. Wallet security models built before that date assumed an EOA's execution was fixed; afterwards, that assumption is wrong. Wintermute's 30-day post-fork data showed that more than 97% of mainnet delegations went to sweeper contracts, and the first major user losses to 7702-specific phishing followed within months. Pectra is the activation date, not just a milestone.
3. Is EIP-7702 the same as ERC-4337 account abstraction?
No — they solve overlapping problems through different layers. ERC-4337 is an off-chain plus on-chain account abstraction system that uses a singleton EntryPoint contract and a parallel mempool of
UserOperation structs handled by bundlers and paymasters. It works without any protocol change. EIP-7702 is an in-protocol change: it adds transaction type 0x04 and lets an EOA delegate its execution to any contract with a single signature, no separate deployment, no new address. The two were designed to compose — a 7702-delegated EOA can be the smart account that an ERC-4337 bundler routes through — but they are not the same standard, and they introduce different security trade-offs. Our ERC-4337 failure modes piece covers the 4337-specific bugs in detail.4. What is a 7702 "delegate contract" and what does it take to make one safe?
A delegate contract is the implementation contract that a 7702-delegated EOA points to. When anyone calls the EOA's address, the EVM follows the
0xef0100 || address designator and runs the delegate's code in the EOA's storage context. A safe delegate authenticates every state-changing call by verifying a signature from the EOA's authority that commits to a nonce, the call's value, the gas limit, and the target + calldata. Miss any of these and the spec's "Secure delegation" invariants are violated: missing nonce enables replay, missing value lets a sponsor change ETH amounts, missing gas allows starvation, and missing target/calldata gives the sponsor an unconstrained power of attorney. Safe delegates also use ERC-7201 namespaced storage to avoid collisions across redelegations, and either batch initialization with delegation or authenticate initialize to prevent frontrunning.5. How can my protocol detect that the caller is a 7702-delegated EOA?
Read the first three bytes of
msg.sender.code and check for the 0xef0100 prefix. That sequence is the delegation designator — the EVM writes it as the entire code of any EOA that has been delegated under EIP-7702. The check is cheap (one EXTCODECOPY of three bytes) and unambiguous: regular EOAs have empty code, regular contracts have arbitrary bytecode that does not start with 0xef (because EIP-3541 banned that prefix for normal deployments), and only 7702-delegated EOAs match. As a secondary signal, EXTCODESIZE returns 2 for a delegated EOA, 0 for a true EOA, and ≥ 23 for a regular contract. Either way, do not rely on tx.origin == msg.sender to make this distinction; a delegated EOA satisfies that equality just like a regular EOA does.6. Should my protocol still rely on `msg.sender == tx.origin` after EIP-7702?
No. The EIP-7702 spec is explicit that
tx.origin == msg.sender is no longer a reliable topmost-frame check, because a 7702-delegated EOA can be the transaction origin and yet be running arbitrary smart contract code. If you were using the equality for reentrancy protection, replace it with ReentrancyGuard or a transient-storage mutex — the article on reentrancy attacks covers the modern patterns. If you were using it as an anti-sandwich signal, accept that the protection is gone for delegated EOAs. And if you were treating "EOA-only access" as a safety property (a common pattern in lottery, faucet, or anti-bot logic), your assumption is now broken: add the 0xef0100 prefix check from the previous question as the explicit gate.Glossary
| Term | Definition |
|---|---|
| EIP-7702 | Ethereum protocol upgrade (Pectra, May 7 2025) that lets an EOA delegate execution to a smart contract via a signed authorization tuple. |
| Account Abstraction | Design pattern that replaces fixed EOA logic with programmable smart-contract accounts for custom validation, recovery, and gas payment. |
| Delegatecall | EVM opcode that executes another contract's code in the caller's storage context — the mechanism that powers 7702 delegate execution. |
| UserOperation | ERC-4337 transaction-like struct submitted to bundlers; the activation vector for 7702-delegated EOAs in hybrid AA stacks. |
| Tx.origin | Solidity global pointing to the transaction sender; no longer reliable as an "is this an EOA" check after EIP-7702. |
| Replay Attack | Reuse of a signed message in a context the signer did not intend — the threat model behind 7702's chain_id = 0 issue. |
Related reading on the Zealynx blog:
- ERC-4337 smart accounts: six failure modes we're already seeing in audits — the wallet-side bugs that compose with 7702 in hybrid account-abstraction stacks.
- 2025 exploit lessons: $3.4B in DeFi losses and what they revealed — the presentation-layer and supply-chain failures that defined the year EIP-7702 shipped.
- UUPS vs Transparent vs Beacon: proxy security guide 2026 — the DELEGATECALL mechanics, storage-layout discipline, and ERC-7201 patterns that apply directly to delegate-contract design.
- tx.origin phishing in Solidity — the classical anti-pattern that EIP-7702 turns from a theoretical risk into a default one.
Are you audit-ready?
Download the free Pre-Audit Readiness Checklist used by 30+ protocols preparing for their first audit.
No spam. Unsubscribe anytime.
