Ownable standard by default, which gives deployed contracts flexible, secure administration. But these contracts expose two distinct control roles, the Owner and the Delegate, and decisions about transferring or renouncing them must be made carefully. This page explains what each role controls, why they usually share one address, and how to hand both to a multisig without bricking your configuration.
Contract Ownership Pattern
When you deploy a LayerZero contract, the trailing constructor argument seeds both roles at once:_delegate value is passed to two base constructors:
OFT(..., _delegate)registers_delegateas the contract’s Delegate inside the LayerZero Endpoint.Ownable(_delegate)sets_delegateas the contract Owner.
examples/oft/contracts/MyOFT.sol (OFT already inherits Ownable, so MyOFT only needs to list OFT and pass Ownable(_delegate) in its constructor).
Some quickstarts name this argument
_owner instead of _delegate (see the OFT quickstart and OApp overview). It is the same mechanic with a different label.delegates mapping, not on your contract. Calling setDelegate() on your OApp writes that value on the Endpoint. See setDelegate in the Endpoint V2 API.
Understanding Owner vs Delegate
The two roles control different layers of your application:
The Owner is the only role that can change the Delegate; the Delegate cannot change the Owner. For the full per-role permission table, see Security and roles and the Delegate glossary entry.
RBAC variant: Some OApps replace
Ownable with role-based access control, for example the Stablecoin OFT, where DEFAULT_ADMIN_ROLE replaces the single owner and setDelegate() is disabled. The guidance on this page applies to standard Ownable OApp and OFT contracts; see the RBAC reference for that model.Why They Should Match
Keep the Owner and the Delegate set to the same address unless you have a specific reason to split them:- Our wiring tooling (
lz:oapp:wire) calls both owner-gated functions (setPeer,setEnforcedOptions) and delegate-gated Endpoint functions (setConfig) in a single run. If the two roles are different addresses, the run reverts on whichever calls the signer is not authorized for: owner-gated calls revert through OpenZeppelinOwnable(OwnableUnauthorizedAccount), and delegate-gated Endpoint calls revert withLZ_Unauthorizedfrom the Endpoint. - Fewer privileged addresses means a smaller attack surface and simpler multisig management.
Transferring Control Safely
One ordering rule matters a great deal when you move control to a new address: If you transfer ownership to your multisig first but leave the old EOA as the Delegate, later Endpoint calls (for examplesetSendLibrary() during wiring) revert, because the multisig is not the Delegate yet. For that reason our own tooling moves the Delegate first, then the Owner.
A correct manual sequence:
delegate and owner fields in layerzero.config.ts, then use the wiring flow and npx hardhat lz:ownable:transfer-ownership. See Adding a delegate and Adding an owner.
Use a Multisig for Both Roles
Whatever address holds these roles can reconfigure your application, so our recommendation is direct:- Retain control with a secure multisig. Do not renounce ownership of critical contracts. Transfer both roles to a multisig and choose a quorum that no single party can satisfy alone.
- Owner and Delegate are equally sensitive. The split is functional (application vs protocol), not a difference in blast radius: each role can ultimately reconfigure peers or security and disrupt your messaging. Secure both equally.
- Stay flexible. Keeping control lets you adjust peers, delegates, DVN configuration, and enforced options as your crosschain deployment evolves.
- Document and audit. Record who holds each role, and review your multisig signers and quorum regularly.
Transfer to a Safe Multisig
Safe (formerly Gnosis Safe) is the common choice for the Owner and Delegate multisig. Rather than transferring by hand, add asafeConfig block (with safeUrl and safeAddress) to the relevant network in your hardhat.config.ts, then push the ownership and wiring transactions through the Safe for approval with the lz:oapp:wire --safe flag. The full setup is documented in Wiring via Safe multisig.
To call transferOwnership(), setDelegate(), or any owner function interactively against your own deployment, use the contracts playground.
Non-EVM Caveats
Owner and Delegate are distinct roles on Solana too, but the address you register is VM-specific and easy to get wrong. With a Squads multisig, the owner and delegate must be the Squads Vault address, not the Multisig Account address; our tooling rejects the Multisig Account address for these roles. You pass the Multisig Account address only through the
--multisig-key helper flag, and the tooling derives the Vault (at index 0) from it. Setting the wrong account here is hard to undo, so follow the exact steps in Transferring OFT ownership on Solana.Summary
- The Owner controls application policy (
setPeer,setEnforcedOptions); the Delegate controls Endpoint and security config (setConfig, libraries, message recovery). - They start as the same address at deploy and should usually stay that way; a mismatch makes wiring revert on whichever role’s calls the signer is not authorized for.
- Set the Delegate before you transfer ownership, because only the Owner can call
setDelegate(). - Use a multisig for both roles. Do not use an EOA for production ownership.
- Do not renounce ownership unless you intend permanent, unrecoverable immutability.