Peripheral Contracts
Emissaries
Emissaries provide a fallback verification mechanism for sponsors when authorizing claims. This is particularly useful for:
- Smart contract accounts that might update their EIP-1271 signature verification logic.
- Accounts using EIP-7702 delegation that leverages EIP-1271.
- Situations where the sponsor wants to delegate claim verification to a trusted third party.
A sponsor assigns an emissary for a specific lockTag
using assignEmissary
. The emissary must implement the IEmissary
interface, specifically the verifyClaim
function.
To change an emissary after one has been assigned, the sponsor must first call scheduleEmissaryAssignment
, wait for the resetPeriod
associated with the lockTag
to elapse, and then call assignEmissary
again with the new emissary's address (or address(0)
to remove).
IEmissary Interface
Emissaries must implement the IEmissary
interface to integrate with The Compact:
interface IEmissary {
function verifyClaim(
address sponsor,
bytes32 digest,
bytes32 claimHash,
bytes calldata signature,
bytes12 lockTag
) external view returns (bytes4)
}
Requirements:
- Must return
IEmissary.verifyClaim.selector
on successful verification
Assignment and Management
Assigning an Emissary
Sponsors assign emissaries for specific lock tags:
function assignEmissary(
bytes12 lockTag,
address emissary
) external
Parameters:
lockTag
: The specific resource lock tag this emissary will be authorized foremissary
: The address of the emissary contract (oraddress(0)
to remove)
The emissary assignment is scoped to a specific lockTag
, meaning sponsors can have different emissaries for different resource locks.
Changing an Emissary
The emissary mechanism includes security timelocks to prevent sudden authorization changes:
- Schedule the Change: Call
scheduleEmissaryAssignment
with the new emissary address - Wait Period: Wait for the
resetPeriod
associated with thelockTag
to elapse - Execute Assignment: Call
assignEmissary
again with the new address
function scheduleEmissaryAssignment(
bytes12 lockTag,
address newEmissary
) external
Removing an Emissary
To remove an emissary, assign address(0)
:
assignEmissary(lockTag, address(0))
Security Rationale
This timelock mechanism ensures that emissary changes cannot suddenly alter the authorization logic for outstanding compacts without providing adequate notice. This protects claimants who may have already begun fulfilling compact conditions based on the existing emissary.
Role in Claim Verification
When a claim is submitted for a non-registered compact, The Compact verifies the sponsor's authorization in the following order:
- Caller is Sponsor: If
msg.sender == sponsor
, authorization is granted - ECDSA Signature: Attempt standard ECDSA signature verification
- EIP-1271
isValidSignature
: If ECDSA fails, callisValidSignature
on the sponsor's address (if it's a contract) with half the remaining gas - Emissary
verifyClaim
: If EIP-1271 fails or isn't applicable, and an emissary is assigned for the sponsor andlockTag
, call the emissary'sverifyClaim
function
Events
event EmissaryAssigned(
address indexed sponsor,
bytes12 indexed lockTag,
address emissary
)
Emitted when a sponsor assigns or changes an emissary via assignEmissary
.
Trust Assumptions
Sponsors must trust that emissaries will not authorize claims maliciously, as emissaries effectively have the same authorization power as the sponsor for claim verification.
Claimants must trust that emissaries (if assigned) will faithfully authorize valid claims. For EIP-7702 sponsors and smart contracts with upgradeable EIP-1271 logic, claimants should require the use of known, canonical emissaries that enforce delays before allowing key rotation.
Tribunal
Tribunal is a framework for processing cross-chain swap settlements against PGA (priority gas auction) blockchains. It ensures that tokens are transferred according to the mandate specified by the originating sponsor and enforces that a single party is able to perform the settlement in the event of a dispute.
Tribunal is a reference implementation, not part of The Compact core protocol. The Compact itself is an unopinionated primitive that doesn't depend on or have awareness of any specific settlement engine. Tribunal is included in this documentation as an example that demonstrates how developers can build cross-chain settlement systems on top of The Compact.
Other teams can (and should) build their own settlement engines with different trust assumptions, auction mechanisms, or cross-chain messaging approaches. Tribunal simply shows one proven pattern for orchestrating cross-chain fills and settlements using The Compact's resource locks.
Status: Tribunal is actively under development. For the latest updates and implementation details, see the Tribunal repository.
How Tribunal Works
Fillers call fill
and provide any native value necessary to pay for cross-chain messaging. Tribunal verifies expiry, chain IDs, validity conditions, computes hashes and amounts, and then executes the settlement:
- Transfers the filled tokens to the intended recipient
- For same-chain fills: Claims tokens via The Compact and calls back into the arbiter or recipient
- For cross-chain fills: Emits or processes directives that instruct remote arbiters to pull the claim
By enforcing a single settlement path, Tribunal eliminates disputes and ensures fairness even in the presence of multiple fillers.
Extending Tribunal
External bridge protocols can extend Tribunal by overriding internal functions to implement the relevant directive processing logic for passing a message to the arbiter on the claim chain (or ensure that the necessary state is updated to allow for the arbiter to "pull" the message themselves).