Perennial's intent system has a light footprint onchain. It uses a few modules ot extend the standard update() functionality of the markets.
Intent Structure
Intents take the form of an EIP-712 signed message. Below is the structure of an intent order:
{
"amount": // The size and direction of the order being opened by the taker
// - Positive opens long / Negative opens short
// - The maker will open the opposite side of the order
// - To close, open an order in the opposite direction
"price": // The price to execute the order at
"fee": // The solver fee, a percentage of the substractive interface fee
"originator": // The referral address of the originator of the order (ex. the interface)
"solver": // The referral address of the solver of the order (ex. the router)
"collateralization": // The minimium collateralization ratio that must be maintained after the order is executed
"common": {
"account": // The target account of the message (usually the account on behalf of which the action is being performed)
"signer": // EOA signing the message (usually either the account or a delegate of the account)
"domain": // ensures the message is unique to a particular protocol version, chain, and verifier
"nonce": // per-sender nonce which is automatically cancelled upon validation
"group": // per-sender nonce which must be manually cancelled with a GroupCancellation message
"expiry": // prevents this message from having the intended effect after a specified timestamp
}
}
Market - Update()
These signed Intents submitted by a Maker to the intent specific update() function on each market instance.
/// @notice Updates both the long and short positions of an intent order
/// @dev - One side is specified in the signed intent, while the sender is assumed to be the counterparty
/// - The sender is charged the settlement fee
/// @param account The account that is filling this intent (maker)
/// @param intent The intent that is being filled
/// @param signature The signature of the intent that is being filled
function update(address account, Intent calldata intent, bytes memory signature) external nonReentrant whenNotPaused {
if (intent.fee.gt(UFixed6Lib.ONE)) revert MarketInvalidIntentFeeError();
verifier.verifyIntent(intent, signature);
_updateIntent(
account,
address(0),
intent.amount.mul(Fixed6Lib.NEG_ONE),
intent.price,
address(0),
address(0),
UFixed6Lib.ZERO,
UFixed6Lib.ZERO,
true,
false
); // account
_updateIntent(
intent.common.account,
intent.common.signer,
intent.amount,
intent.price,
intent.originator,
intent.solver,
intent.fee,
intent.collateralization,
false,
true
); // signer
}
Key to operation of the intent system is the intent verifier. This contract checks the validity of the intent, the signature, and if the signer is approved as a signer on the account.