Synapse Interchain logo


GitHub Workflow Status (with event) GitHub Workflow Status (with event) Static Badge npm

@synapsecns/contracts-core contain the Solidity contracts used within the Synapse Interchain Network messaging system.

Usage

These contracts can be installed with:

npm i @synapsecns/contracts-core

Please refer to our usage guide or examples

Directory Structure

root
├── contracts: Contains core contracts
│   ├── base: Base contracts of the protocol
│   ├── client: Client contracts for callers of the messaging system.
│   ├── events: Event types
│   ├── hubs: Hubs
│   ├── inbox: Inbox contracts
│   ├── interfaces: Interfaces
│   ├── libs: Library contracts
│   ├── Manager: Manager contracts
├── deployments: Non-devnet deployments of the contracts
├── lib: Git-module based dependencies
├── script: Scripts for deploying + interacting with contracts
├── test: Test contracts

Running a devnet

To run a devnet, you can run make devnet-up and make devnet-deploy from this directory. This will start a local devnet and deploy the contracts to it. RPC endpoints for debugging etc will be availabe at http://localhost:9001/rpc/[chain_id].

By default, the PingPongClient.sol is deployed, so you can interact with it with cast. For instance, to send a ping from chain 42 to chain 44:

cast send 0x521F44132489CDD54c9ceC8167CfC377CbAEa351 --rpc-url http://localhost:9001/rpc/42 --private-key 0x526db1890baf94e82162f17f25ad769eb7f981272d8d99c527ea1af443c2d0cc "doPing(uint32,address,uint16)" 44 0x521F44132489CDD54c9ceC8167CfC377CbAEa351 1

Now, to make sure it work, you can pull up scribe by going to http://localhost:9002/graphiql and querying the logs for chain 44:

{

  logs(chain_id: 44, page: 1){
    topics
    block_number
    contract_address
  }
}

If everything went well, you will see topic 0x0a72872b9cfe43d6c13b13553f28d4879e427f3b456545649fd0761fdcbe0311 in the logs, which is the topic for the PingPongClient's Pong event.

graphql screenshot

Contents

AgentSecured

Git Source

Inherits: MessagingBase, IAgentSecured

Base contract for messaging contracts that are secured by the agent manager. AgentSecured relies on AgentManager to provide the following functionality:

  • Keep track of agents and their statuses.
  • Pass agent-signed statements that were verified by the agent manager.
  • These statements are considered valid indefinitely, unless the agent is disputed.
  • Disputes are opened and resolved by the agent manager.

AgentSecured implementation should never use statements signed by agents that are disputed.

State Variables

agentManager

Returns the address of the local AgentManager contract, which is treated as the "source of truth" for agent statuses.

address public immutable agentManager;

inbox

Returns the address of the local Inbox contract, which is treated as the "source of truth" for agent-signed statements.

Inbox passes verified agent statements to IAgentSecured contract.

address public immutable inbox;

_disputes

mapping(uint32 => DisputeStatus) internal _disputes;

__GAP

gap for upgrade safety

uint256[49] private __GAP;

Functions

onlyAgentManager

modifier onlyAgentManager();

onlyInbox

modifier onlyInbox();

constructor

constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)
    MessagingBase(version_, synapseDomain_);

openDispute

Local AgentManager should call this function to indicate that a dispute between a Guard and a Notary has been opened.

function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager;

Parameters

NameTypeDescription
guardIndexuint32Index of the Guard in the Agent Merkle Tree
notaryIndexuint32Index of the Notary in the Agent Merkle Tree

resolveDispute

Local AgentManager should call this function to indicate that a dispute has been resolved due to one of the agents being slashed.

rivalIndex will be ZERO, if the slashed agent was not in the Dispute.

function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager;

Parameters

NameTypeDescription
slashedIndexuint32Index of the slashed agent in the Agent Merkle Tree
rivalIndexuint32Index of the their Dispute Rival in the Agent Merkle Tree

agentStatus

Returns (flag, domain, index) for a given agent. See Structures.sol for details.

Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.

function agentStatus(address agent) external view returns (AgentStatus memory);

Parameters

NameTypeDescription
agentaddressAgent address

Returns

NameTypeDescription
<none>AgentStatusStatus for the given agent: (flag, domain, index).

getAgent

Returns agent address and their current status for a given agent index.

Will return empty values if agent with given index doesn't exist.

function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);

Parameters

NameTypeDescription
indexuint256Agent index in the Agent Merkle Tree

Returns

NameTypeDescription
agentaddressAgent address
statusAgentStatusStatus for the given agent: (flag, domain, index)

latestDisputeStatus

Returns (flag, openedAt, resolvedAt) that describes the latest status of the latest dispute for an agent with a given index.

Will return empty values if agent with given index doesn't exist.

function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);

Parameters

NameTypeDescription
agentIndexuint32Agent index in the Agent Merkle Tree

Returns

NameTypeDescription
<none>DisputeStatusLatest dispute status for the given agent: (flag, openedAt, resolvedAt)

_agentStatus

Returns status of the given agent: (flag, domain, index).

function _agentStatus(address agent) internal view returns (AgentStatus memory);

_getAgent

Returns agent and their status for a given agent index. Returns zero values for non existing indexes.

function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status);

_notaryDisputeExists

Checks if a Dispute exists for the given Notary. This function returns true, if Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor. In both cases we can't trust Notary's data. Note: Agent-Secured contracts can trust Notary data only if both _notaryDisputeExists and _notaryDisputeTimeout return false.

function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool);

_notaryDisputeTimeout

Checks if a Notary recently won a Dispute and is still in the "post-dispute" timeout period. In this period we still can't trust Notary's data, though we can optimistically assume that that the data will be correct after the timeout (assuming no new Disputes are opened). Note: Agent-Secured contracts can trust Notary data only if both _notaryDisputeExists and _notaryDisputeTimeout return false.

function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool);

MessagingBase

Git Source

Inherits: MultiCallable, Versioned, Ownable2StepUpgradeable

Base contract for all messaging contracts.

  • Provides context on the local chain's domain.
  • Provides ownership functionality.
  • Will be providing pausing functionality when it is implemented.

State Variables

localDomain

Domain of the local chain, set once upon contract creation

uint32 public immutable localDomain;

synapseDomain

uint32 public immutable synapseDomain;

__GAP

gap for upgrade safety

uint256[50] private __GAP;

Functions

constructor

constructor(string memory version_, uint32 synapseDomain_) Versioned(version_);

renounceOwnership

Should be impossible to renounce ownership; we override OpenZeppelin OwnableUpgradeable's implementation of renounceOwnership to make it a no-op

function renounceOwnership() public override onlyOwner;

MultiCallable

Git Source

Collection of Multicall utilities. Fork of Multicall3: https://github.com/mds1/multicall/blob/master/src/Multicall3.sol

Functions

multicall

Aggregates a few calls to this contract into one multicall without modifying msg.sender.

function multicall(Call[] calldata calls) external returns (Result[] memory callResults);

Structs

Call

struct Call {
    bool allowFailure;
    bytes callData;
}

Result

struct Result {
    bool success;
    bytes returnData;
}

Versioned

Git Source

Version getter for contracts. Doesn't use any storage slots, meaning it will never cause any troubles with the upgradeable contracts. For instance, this contract can be added or removed from the inheritance chain without shifting the storage layout.

State Variables

_length

Length of the "version string"

uint256 private immutable _length;

_data

Bytes representation of the "version string". Strings with length over 32 are not supported!

bytes32 private immutable _data;

Functions

constructor

constructor(string memory version_);

version

function version() external view returns (string memory versionString);

Structs

_ShortString

Struct that is mimicking the storage layout of a string with 32 bytes or less. Length is limited by 32, so the whole string payload takes two memory words:

struct _ShortString {
    uint256 length;
    bytes32 data;
}

Contents

BaseClient

Git Source

Inherits: MessageRecipient

*Implementation of IMessageRecipient interface, to be used as the recipient of base messages passed by the Destination contract. BaseClient could be used as a backbone for cross-chain apps:

  • A single BaseClient contract per chain (aka trusted sender)
  • Only BaseClient instances from other chains are able to send messages to this contract
  • BaseClient enforces a common optimistic period for all types of messages Note: BaseClient is forever stateless, meaning it can be potentially used as a parent for the upgradeable contract without worrying about storage collision.*

Functions

constructor

constructor(address origin_, address destination_) MessageRecipient(origin_, destination_);

optimisticPeriod

Period of time since the root was submitted to Destination. Once this period is over, root can be used for proving and executing a message though this Client.

function optimisticPeriod() public view virtual returns (uint32);

trustedSender

Address of the trusted sender on the destination chain. The trusted sender will be able to:

  • Send messages to this contract from other chains.
  • Receive messages from this contract on other chains.
function trustedSender(uint32 destination) public view virtual returns (bytes32);

_receiveBaseMessageUnsafe

*Child contracts should implement the logic for receiving a Base Message in an "unsafe way". Following checks HAVE been performed:

  • receiveBaseMessage() was called by Destination (i.e. this is a legit base message).
  • Nonce is not zero.
  • Message sender on origin chain is not a zero address.
  • Proof maturity is not zero. Following checks HAVE NOT been performed (thus "unsafe"):
  • Message sender on origin chain could be anything non-zero at this point.
  • Proof maturity could be anything non-zero at this point.*
function _receiveBaseMessageUnsafe(
    uint32 origin_,
    uint32 nonce,
    bytes32 sender,
    uint256 proofMaturity,
    uint32 version,
    bytes memory content
) internal override;

_receiveBaseMessage

*Child contracts should implement the logic for receiving a Base Message. Following checks HAVE been performed:

  • receiveBaseMessage() was called by Destination (i.e. this is a legit base message).
  • Nonce is not zero.
  • Message sender on origin chain is a trusted sender (and is not zero).
  • Optimistic period for the message have passed (and is not zero).*
function _receiveBaseMessage(uint32 origin_, uint32 nonce, uint32 version, bytes memory content) internal virtual;

_sendBaseMessage

*Sends a message to given destination chain. Full msg.value is used to pay for the message tips. _getMinimumTipsValue() could be used to calculate the minimum required tips value, and should be also exposed as a public view function to estimate the tips value before sending a message off-chain. This function is not exposed in BaseClient, as the message encoding is implemented by the child contract.

Will revert if the trusted sender is not set for the destination domain.*

function _sendBaseMessage(uint32 destination_, uint256 tipsValue, MessageRequest memory request, bytes memory content)
    internal
    returns (uint32 messageNonce, bytes32 messageHash);

Parameters

NameTypeDescription
destination_uint32Domain of the destination chain
tipsValueuint256Tips to be paid for sending the message
requestMessageRequestEncoded message execution request on destination chain
contentbytesThe message content

MessageRecipient

Git Source

Inherits: IMessageRecipient

State Variables

origin

Local chain Origin: used for sending messages

address public immutable origin;

destination

Local chain Destination: used for receiving messages

address public immutable destination;

Functions

constructor

constructor(address origin_, address destination_);

receiveBaseMessage

Message recipient needs to implement this function in order to receive cross-chain messages.

Message recipient needs to ensure that merkle proof for the message is at least as old as the optimistic period that the recipient is using. Note: as this point it is checked that the "message optimistic period" has passed, however the period value itself could be anything, and thus could differ from the one that the recipient would like to enforce.

function receiveBaseMessage(
    uint32 origin_,
    uint32 nonce,
    bytes32 sender,
    uint256 proofMaturity,
    uint32 version,
    bytes memory content
) external payable;

Parameters

NameTypeDescription
origin_uint32
nonceuint32Message nonce on the origin domain
senderbytes32Sender address on origin chain
proofMaturityuint256Message's merkle proof age in seconds
versionuint32Message version specified by sender
contentbytesRaw bytes content of message

_receiveBaseMessageUnsafe

*Child contracts should implement the logic for receiving a Base Message in an "unsafe way". Following checks HAVE been performed:

  • receiveBaseMessage() was called by Destination (i.e. this is a legit base message).
  • Nonce is not zero.
  • Message sender on origin chain is not a zero address.
  • Proof maturity is not zero. Following checks HAVE NOT been performed (thus "unsafe"):
  • Message sender on origin chain could be anything non-zero at this point.
  • Proof maturity could be anything non-zero at this point.*
function _receiveBaseMessageUnsafe(
    uint32 origin_,
    uint32 nonce,
    bytes32 sender,
    uint256 proofMaturity,
    uint32 version,
    bytes memory content
) internal virtual;

_sendBaseMessage

Sends a message to given destination chain. Full msg.value is used to pay for the message tips. _getMinimumTipsValue() could be used to calculate the minimum required tips value, and should be also exposed as a public view function to estimate the tips value before sending a message off-chain. This function is not exposed in MessageRecipient, as the message encoding is implemented by the child contract.

function _sendBaseMessage(
    uint32 destination_,
    bytes32 recipient,
    uint32 optimisticPeriod,
    uint256 tipsValue,
    MessageRequest memory request,
    bytes memory content
) internal returns (uint32 messageNonce, bytes32 messageHash);

Parameters

NameTypeDescription
destination_uint32Domain of the destination chain
recipientbytes32Address of the recipient on destination chain
optimisticPerioduint32Optimistic period for the message
tipsValueuint256Tips to be paid for sending the message
requestMessageRequestMessage execution request on destination chain
contentbytesThe message content

_getMinimumTipsValue

Returns the minimum tips value for sending a message to given destination chain.

function _getMinimumTipsValue(uint32 destination_, MessageRequest memory request, uint256 contentLength)
    internal
    view
    returns (uint256 tipsValue);

Parameters

NameTypeDescription
destination_uint32Domain of the destination chain
requestMessageRequestMessage execution request on destination chain
contentLengthuint256Length of the message content

_encodeRequest

Encodes a message execution request into format that Origin contract is using.

function _encodeRequest(MessageRequest memory request) internal pure returns (uint256 paddedRequest);

Parameters

NameTypeDescription
requestMessageRequestMessage execution request on destination chain

Returns

NameTypeDescription
paddedRequestuint256Encoded request

Structs

MessageRequest

struct MessageRequest {
    uint96 gasDrop;
    uint64 gasLimit;
    uint32 version;
}

PingPongClient

Git Source

Inherits: MessageRecipient

State Variables

random

uint256 public random;

pingsSent

Amount of "Ping" messages sent.

uint256 public pingsSent;

pingsReceived

Amount of "Ping" messages received. Every received Ping message leads to sending a Pong message back to initial sender.

uint256 public pingsReceived;

pongsReceived

Amount of "Pong" messages received. When all messages are delivered, should be equal to pingsSent

uint256 public pongsReceived;

Functions

constructor

constructor(address origin_, address destination_) MessageRecipient(origin_, destination_);

doPings

function doPings(uint16 pingCount, uint32 destination_, address recipient, uint16 counter) external;

doPing

Send a Ping message to destination chain. Upon receiving a Ping, a Pong message will be sent back. If counter > 0, this process will be repeated when the Pong message is received.

function doPing(uint32 destination_, address recipient, uint16 counter) external;

Parameters

NameTypeDescription
destination_uint32Chain to send Ping message to
recipientaddressRecipient of Ping message
counteruint16Additional amount of Ping-Pong rounds to conclude

nextOptimisticPeriod

function nextOptimisticPeriod() public view returns (uint32 period);

_receiveBaseMessageUnsafe

*Child contracts should implement the logic for receiving a Base Message in an "unsafe way". Following checks HAVE been performed:

  • receiveBaseMessage() was called by Destination (i.e. this is a legit base message).
  • Nonce is not zero.
  • Message sender on origin chain is not a zero address.
  • Proof maturity is not zero. Following checks HAVE NOT been performed (thus "unsafe"):
  • Message sender on origin chain could be anything non-zero at this point.
  • Proof maturity could be anything non-zero at this point.*
function _receiveBaseMessageUnsafe(uint32 origin_, uint32, bytes32 sender, uint256, uint32, bytes memory content)
    internal
    override;

_optimisticPeriod

Returns a random optimistic period value from 0 to 59 seconds.

function _optimisticPeriod() internal returns (uint32 period);

_sendMessage

Send a "Ping" or "Pong" message.

function _sendMessage(uint32 destination_, bytes32 recipient, PingPongMessage memory message) internal;

Parameters

NameTypeDescription
destination_uint32Domain of destination chain
recipientbytes32Message recipient on destination chain
messagePingPongMessagePing-pong message

_ping

Initiate a new Ping-Pong round.

function _ping(uint32 destination_, bytes32 recipient, uint16 counter) internal;

_pong

Send a Pong message back.

function _pong(uint32 destination_, bytes32 recipient, PingPongMessage memory message) internal;

Events

PingSent

Emitted when a Ping message is sent. Triggered externally, or by receveing a Pong message with instructions to do more pings.

event PingSent(uint256 pingId);

PingReceived

Emitted when a Ping message is received. Will always send a Pong message back.

event PingReceived(uint256 pingId);

PongSent

Emitted when a Pong message is sent. Triggered whenever a Ping message is received.

event PongSent(uint256 pingId);

PongReceived

Emitted when a Pong message is received. Will initiate a new Ping, if the counter in the message is non-zero.

event PongReceived(uint256 pingId);

Structs

PingPongMessage

struct PingPongMessage {
    uint256 pingId;
    bool isPing;
    uint16 counter;
}

TestClient

Git Source

Inherits: MessageRecipient

Functions

constructor

constructor(address origin_, address destination_) MessageRecipient(origin_, destination_);

sendMessage

function sendMessage(
    uint32 destination_,
    address recipientAddress,
    uint32 optimisticPeriod,
    uint64 gasLimit,
    uint32 version,
    bytes memory content
) external payable;

_receiveBaseMessageUnsafe

*Child contracts should implement the logic for receiving a Base Message in an "unsafe way". Following checks HAVE been performed:

  • receiveBaseMessage() was called by Destination (i.e. this is a legit base message).
  • Nonce is not zero.
  • Message sender on origin chain is not a zero address.
  • Proof maturity is not zero. Following checks HAVE NOT been performed (thus "unsafe"):
  • Message sender on origin chain could be anything non-zero at this point.
  • Proof maturity could be anything non-zero at this point.*
function _receiveBaseMessageUnsafe(
    uint32 origin_,
    uint32 nonce,
    bytes32 sender,
    uint256 proofMaturity,
    uint32 version,
    bytes memory content
) internal override;

Events

MessageReceived

event MessageReceived(
    uint32 origin, uint32 nonce, bytes32 sender, uint256 proofMaturity, uint32 version, bytes content
);

MessageSent

event MessageSent(uint32 destination, uint32 nonce, bytes32 sender, bytes32 recipient, bytes content);

Contents

AgentManagerEvents

Git Source

Events

DisputeOpened

Emitted whenever a Dispute is opened between two agents. This happens when a Guard submits their report for the Notary-signed statement to StatementInbox.

event DisputeOpened(uint256 disputeIndex, uint32 guardIndex, uint32 notaryIndex);

DisputeResolved

Emitted whenever a Dispute is resolved. This happens when an Agent who was in Dispute is slashed. Note: this won't be emitted, if an Agent was slashed without being in Dispute.

event DisputeResolved(uint256 disputeIndex, uint32 slashedIndex, uint32 rivalIndex, address fraudProver);

RootUpdated

Emitted whenever the root of the Agent Merkle Tree is updated.

event RootUpdated(bytes32 newRoot);

AgentRootProposed

Emitted after the contract owner proposes a new agent root to resolve the stuck chain.

event AgentRootProposed(bytes32 newRoot);

ProposedAgentRootCancelled

Emitted after the contract owner cancels the previously proposed agent root.

event ProposedAgentRootCancelled(bytes32 proposedRoot);

ProposedAgentRootResolved

Emitted after the contract owner resolves the previously proposed agent root.

event ProposedAgentRootResolved(bytes32 proposedRoot);

StatusUpdated

Emitted whenever a status of the agent is updated.

Only Active/Unstaking/Resting/Slashed flags could be stored in the Agent Merkle Tree. Unknown flag is the default (zero) value and is used to represent agents that never interacted with the BondingManager contract. Fraudulent flag is the value for the agent who has been proven to commit fraud, but their status hasn't been updated to Slashed in the Agent Merkle Tree. This is due to the fact that the update of the status requires a merkle proof of the old status, and happens in a separate transaction because of that.

event StatusUpdated(AgentFlag flag, uint32 indexed domain, address indexed agent);

DestinationEvents

Git Source

A collection of events emitted by the Destination contract

Events

AgentRootAccepted

event AgentRootAccepted(bytes32 agentRoot);

ExecutionHubEvents

Git Source

A collection of events emitted by the ExecutionHub contract

Events

Executed

Emitted when message is executed.

event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);

TipsRecorded

Emitted when message tips are recorded.

event TipsRecorded(bytes32 messageHash, uint256 paddedTips);

GasOracleEvents

Git Source

A collection of events emitted by the GasOracle contract

Events

GasDataUpdated

Emitted when gas data is updated for the domain

event GasDataUpdated(uint32 domain, uint256 paddedGasData);

SummitTipUpdated

Emitted when the value of the summit tip is updated

event SummitTipUpdated(uint256 summitTipWei);

InboxEvents

Git Source

Events

SnapshotAccepted

Emitted when a snapshot is accepted by the Summit contract.

event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);

ReceiptAccepted

Emitted when a snapshot is accepted by the Summit contract.

event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);

InvalidAttestation

Emitted when a proof of invalid attestation is submitted.

event InvalidAttestation(bytes attPayload, bytes attSignature);

InvalidAttestationReport

Emitted when a proof of invalid attestation report is submitted.

event InvalidAttestationReport(bytes arPayload, bytes arSignature);

OriginEvents

Git Source

A collection of events emitted by the Origin contract

Events

Sent

Emitted when a new message is sent.

event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);

TipWithdrawalCompleted

Emitted when a tip withdrawal is completed.

event TipWithdrawalCompleted(address actor, uint256 tip);

SnapshotHubEvents

Git Source

A collection of events emitted by the SnapshotHub contract

Events

AttestationSaved

Emitted when a new Attestation is saved (derived from a Notary snapshot).

event AttestationSaved(bytes attestation);

StateSaved

Emitted when a new Origin State is saved from a Guard snapshot.

event StateSaved(bytes state);

StateHubEvents

Git Source

A collection of events emitted by the StateHub contract

Events

StateSaved

Emitted when a new Origin State is saved after a message was sent.

event StateSaved(bytes state);

StatementInboxEvents

Git Source

Events

AttestationAccepted

Emitted when a snapshot is accepted by the Destination contract.

event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);

InvalidReceipt

Emitted when a proof of invalid receipt statement is submitted.

event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);

InvalidReceiptReport

Emitted when a proof of invalid receipt report is submitted.

event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);

InvalidStateWithAttestation

Emitted when a proof of invalid state in the signed attestation is submitted.

event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);

InvalidStateWithSnapshot

Emitted when a proof of invalid state in the signed snapshot is submitted.

event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);

InvalidStateReport

Emitted when a proof of invalid state report is submitted.

event InvalidStateReport(bytes srPayload, bytes srSignature);

SummitEvents

Git Source

A collection of events emitted by the Summit contract

Events

TipAwarded

Emitted when a tip is awarded to the actor, whether they are bonded or unbonded actor.

event TipAwarded(address actor, uint32 origin, uint256 tip);

TipWithdrawalInitiated

Emitted when a tip withdrawal is initiated by the actor.

event TipWithdrawalInitiated(address actor, uint32 origin, uint256 tip);

Contents

ExecutionHub

Git Source

Inherits: AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub

ExecutionHub is a parent contract for Destination. It is responsible for the following:

  • Executing the messages that are proven against the saved Snapshot Merkle Roots.
  • Base messages are forwarded to the specified message recipient, ensuring that the original execution request is fulfilled correctly.
  • Manager messages are forwarded to the local AgentManager contract.
  • Keeping track of the saved Snapshot Merkle Roots (which are accepted in Destination).
  • Keeping track of message execution Receipts, as well as verify their validity.

State Variables

_receiptData

(messageHash => status)

Messages coming from different origins will always have a different hash as origin domain is encoded into the formatted message. Thus we can use hash as a key instead of an (origin, hash) tuple.

mapping(bytes32 => ReceiptData) private _receiptData;

_firstExecutor

First executor who made a valid attempt of executing a message. Note: stored only for messages that had Failed status at some point of time

mapping(bytes32 => address) private _firstExecutor;

_roots

All saved snapshot roots

bytes32[] internal _roots;

_rootData

Tracks data for all saved snapshot roots

mapping(bytes32 => SnapRootData) internal _rootData;

__GAP

gap for upgrade safety

uint256[46] private __GAP;

Functions

execute

Attempts to prove inclusion of message into one of Snapshot Merkle Trees, previously submitted to this contract in a form of a signed Attestation. Proven message is immediately executed by passing its contents to the specified recipient.

*Will revert if any of these is true:

  • Message is not meant to be executed on this chain
  • Message was sent from this chain
  • Message payload is not properly formatted.
  • Snapshot root (reconstructed from message hash and proofs) is unknown
  • Snapshot root is known, but was submitted by an inactive Notary
  • Snapshot root is known, but optimistic period for a message hasn't passed
  • Provided gas limit is lower than the one requested in the message
  • Recipient doesn't implement a handle method (refer to IMessageRecipient.sol)
  • Recipient reverted upon receiving a message Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.*
function execute(
    bytes memory msgPayload,
    bytes32[] calldata originProof,
    bytes32[] calldata snapProof,
    uint8 stateIndex,
    uint64 gasLimit
) external nonReentrant;

Parameters

NameTypeDescription
msgPayloadbytesRaw payload with a formatted message to execute
originProofbytes32[]Proof of inclusion of message in the Origin Merkle Tree
snapProofbytes32[]Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree
stateIndexuint8Index of Origin State in the Snapshot
gasLimituint64Gas limit for message execution

getAttestationNonce

Returns attestation nonce for a given snapshot root.

Will return 0 if the root is unknown.

function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);

isValidReceipt

Checks the validity of the unsigned message receipt.

*Will revert if any of these is true:

  • Receipt payload is not properly formatted.
  • Receipt signer is not an active Notary.
  • Receipt destination chain does not refer to this chain.*
function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);

Parameters

NameTypeDescription
rcptPayloadbytesRaw payload with Receipt data

Returns

NameTypeDescription
isValidboolWhether the requested receipt is valid.

messageStatus

Returns message execution status: None/Failed/Success.

function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);

Parameters

NameTypeDescription
messageHashbytes32Hash of the message payload

Returns

NameTypeDescription
statusMessageStatusMessage execution status

messageReceipt

Returns a formatted payload with the message receipt.

Notaries could derive the tips, and the tips proof using the message payload, and submit the signed receipt with the proof of tips to Summit in order to initiate tips distribution.

function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload);

Parameters

NameTypeDescription
messageHashbytes32Hash of the message payload

Returns

NameTypeDescription
rcptPayloadbytesdata Formatted payload with the message execution receipt

_executeBaseMessage

Passes message content to recipient that conforms to IMessageRecipient interface.

function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)
    internal
    returns (bool);

_executeManagerMessage

Uses message body for a call to AgentManager, and checks the returned magic value to ensure that only "remoteX" functions could be called this way.

function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool);

_passReceipt

Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain. This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit without a Notary having to sign them.

function _passReceipt(
    uint32 attNotaryIndex,
    uint32 attNonce,
    bytes32 messageHash,
    uint256 paddedTips,
    ReceiptData memory rcptData
) internal returns (bool);

_saveAttestation

Saves a snapshot root with the attestation data provided by a Notary. It is assumed that the Notary signature has been checked outside of this contract.

function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal;

_isValidReceipt

Checks if receipt body matches the saved data for the referenced message. Reverts if destination domain doesn't match the local domain.

function _isValidReceipt(Receipt rcpt) internal view returns (bool);

_proveAttestation

Attempts to prove the validity of the cross-chain message. First, the origin Merkle Root is reconstructed using the origin proof. Then the origin state's "left leaf" is reconstructed using the origin domain. After that the snapshot Merkle Root is reconstructed using the snapshot proof. The snapshot root needs to have been submitted by an undisputed Notary.

Reverts if any of the checks fail.

function _proveAttestation(
    Header header,
    bytes32 msgLeaf,
    bytes32[] calldata originProof,
    bytes32[] calldata snapProof,
    uint8 stateIndex
) internal view returns (SnapRootData memory rootData);

Parameters

NameTypeDescription
headerHeaderMemory view over the message header
msgLeafbytes32Message Leaf that was inserted in the Origin Merkle Tree
originProofbytes32[]Proof of inclusion of Message Leaf in the Origin Merkle Tree
snapProofbytes32[]Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree
stateIndexuint8Index of Origin State in the Snapshot

Returns

NameTypeDescription
rootDataSnapRootDataData for the derived snapshot root

_messageReceipt

Formats the message execution receipt payload for the given hash and receipt data.

function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)
    internal
    view
    returns (bytes memory rcptPayload);

Structs

SnapRootData

Struct representing stored data for the snapshot root

struct SnapRootData {
    uint32 notaryIndex;
    uint32 attNonce;
    uint40 attBN;
    uint40 attTS;
    uint32 index;
    uint40 submittedAt;
    uint256 sigIndex;
}

ReceiptData

Struct representing stored receipt data for the message in Execution Hub.

struct ReceiptData {
    uint32 origin;
    uint32 rootIndex;
    uint8 stateIndex;
    address executor;
}

SnapshotHub

Git Source

Inherits: AgentSecured, SnapshotHubEvents, ISnapshotHub

SnapshotHub is a parent contract for Summit. It is responsible for the following:

  • Accepting and storing Guard and Notary snapshots to keep track of all the remote Origin states.
  • Generating and storing Attestations derived from Notary snapshots, as well as verifying their validity.

State Variables

_states

All States submitted by any of the Guards

SummitState[] private _states;

_guardSnapshots

All Snapshots submitted by any of the Guards

SummitSnapshot[] private _guardSnapshots;

_notarySnapshots

All Snapshots submitted by any of the Notaries

SummitSnapshot[] private _notarySnapshots;

_attestations

All Attestations created from Notary-submitted Snapshots Invariant: _attestations.length == _notarySnapshots.length

SummitAttestation[] private _attestations;

_leafPtr

Pointer for the given State Leaf of the origin with ZERO as a sentinel value for "state not submitted yet".

mapping(uint32 => mapping(bytes32 => uint256)) private _leafPtr;

_latestStatePtr

Pointer for the latest Agent State of a given origin with ZERO as a sentinel value for "no states submitted yet".

mapping(uint32 => mapping(uint32 => uint256)) private _latestStatePtr;

_latestAttNonce

Latest nonce that a Notary created

mapping(uint32 => uint32) private _latestAttNonce;

__GAP

gap for upgrade safety

uint256[43] private __GAP;

Functions

isValidAttestation

Check that a given attestation is valid: matches the historical attestation derived from an accepted Notary snapshot.

*Will revert if any of these is true:

  • Attestation payload is not properly formatted.*
function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);

Parameters

NameTypeDescription
attPayloadbytesRaw payload with attestation data

Returns

NameTypeDescription
isValidboolWhether the provided attestation is valid

getAttestation

Returns saved attestation with the given nonce.

Reverts if attestation with given nonce hasn't been created yet.

function getAttestation(uint32 attNonce)
    external
    view
    returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);

Parameters

NameTypeDescription
attNonceuint32Nonce for the attestation

Returns

NameTypeDescription
attPayloadbytesRaw payload with formatted Attestation data
agentRootbytes32Agent root hash used for the attestation
snapGasuint256[]Snapshot gas data used for the attestation

getLatestAgentState

Returns the state with the highest known nonce submitted by a given Agent.

function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory stateData);

Parameters

NameTypeDescription
originuint32Domain of origin chain
agentaddressAgent address

Returns

NameTypeDescription
stateDatabytesstatePayload Raw payload with agent's latest state for origin

getLatestNotaryAttestation

Returns latest saved attestation for a Notary.

function getLatestNotaryAttestation(address notary)
    external
    view
    returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);

Parameters

NameTypeDescription
notaryaddressNotary address

Returns

NameTypeDescription
attPayloadbytesRaw payload with formatted Attestation data
agentRootbytes32Agent root hash used for the attestation
snapGasuint256[]Snapshot gas data used for the attestation

getGuardSnapshot

Returns Guard snapshot from the list of all accepted Guard snapshots.

Reverts if snapshot with given index hasn't been accepted yet.

function getGuardSnapshot(uint256 index) external view returns (bytes memory snapPayload, bytes memory snapSignature);

Parameters

NameTypeDescription
indexuint256Snapshot index in the list of all Guard snapshots

Returns

NameTypeDescription
snapPayloadbytesRaw payload with Guard snapshot
snapSignaturebytesRaw payload with Guard signature for snapshot

getNotarySnapshot

Returns Notary snapshot from the list of all accepted Guard snapshots.

Reverts if snapshot with given index hasn't been accepted yet.

function getNotarySnapshot(uint256 index) public view returns (bytes memory snapPayload, bytes memory snapSignature);

Parameters

NameTypeDescription
indexuint256Snapshot index in the list of all Notary snapshots

Returns

NameTypeDescription
snapPayloadbytesRaw payload with Notary snapshot
snapSignaturebytesRaw payload with Notary signature for snapshot

getNotarySnapshot

Returns Notary snapshot from the list of all accepted Guard snapshots.

Reverts if snapshot with given index hasn't been accepted yet.

function getNotarySnapshot(bytes memory attPayload)
    external
    view
    returns (bytes memory snapPayload, bytes memory snapSignature);

Parameters

NameTypeDescription
attPayloadbytes

Returns

NameTypeDescription
snapPayloadbytesRaw payload with Notary snapshot
snapSignaturebytesRaw payload with Notary signature for snapshot

getSnapshotProof

Returns proof of inclusion of (root, origin) fields of a given snapshot's state into the Snapshot Merkle Tree for a given attestation.

*Reverts if any of these is true:

  • Attestation with given nonce hasn't been created yet.
  • State index is out of range of snapshot list.*
function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);

Parameters

NameTypeDescription
attNonceuint32Nonce for the attestation
stateIndexuint8Index of state in the attestation's snapshot

Returns

NameTypeDescription
snapProofbytes32[]The snapshot proof

_acceptGuardSnapshot

Accepts a Snapshot signed by a Guard. It is assumed that the Guard signature has been checked outside of this contract.

function _acceptGuardSnapshot(Snapshot snapshot, uint32 guardIndex, uint256 sigIndex) internal;

_acceptNotarySnapshot

Accepts a Snapshot signed by a Notary. It is assumed that the Notary signature has been checked outside of this contract. Returns the attestation created from the Notary snapshot.

function _acceptNotarySnapshot(Snapshot snapshot, bytes32 agentRoot, uint32 notaryIndex, uint256 sigIndex)
    internal
    returns (bytes memory attPayload);

_initializeAttestations

Initializes the saved _attestations list by inserting empty values.

function _initializeAttestations() internal;

_saveGuardSnapshot

Saves the Guard snapshot.

function _saveGuardSnapshot(uint256[] memory statePtrs, uint256 sigIndex) internal;

_saveNotarySnapshot

Saves the Notary snapshot and the attestation created from it. Returns the created attestation.

function _saveNotarySnapshot(
    Snapshot snapshot,
    uint256[] memory statePtrs,
    bytes32 agentRoot,
    uint32 notaryIndex,
    uint256 sigIndex
) internal returns (bytes memory attPayload);

_saveState

Add a single element to both _attestations and _notarySnapshots, enforcing the (_attestations.length == _notarySnapshots.length) invariant.

Saves the state signed by a Guard.

function _saveState(State state, uint32 guardIndex) internal returns (uint256 statePtr);

_isValidAttestation

Checks if attestation was previously submitted by a Notary (as a signed snapshot).

function _isValidAttestation(Attestation att) internal view returns (bool);

_restoreSnapshot

Restores Snapshot payload from a list of state pointers used for the snapshot.

function _restoreSnapshot(SummitSnapshot memory snapshot)
    internal
    view
    returns (bytes memory snapPayload, bytes memory snapSignature);

_restoreSnapGas

Restores the gas data from the snapshot.

function _restoreSnapGas(SummitSnapshot memory snapshot) internal view returns (uint256[] memory snapGas);

_stateAgents

Returns indexes of agents who provided state data for the Notary snapshot with the given nonce.

function _stateAgents(uint32 nonce, uint8 stateIndex) internal view returns (uint32 guardIndex, uint32 notaryIndex);

_statePtr

Returns the pointer for a matching Guard State, if it exists.

function _statePtr(State state) internal view returns (uint256);

_latestState

Returns the latest state submitted by the Agent for the origin. Will return an empty struct, if the Agent hasn't submitted a single origin State yet.

function _latestState(uint32 origin, uint32 agentIndex) internal view returns (SummitState memory state);

_formatSummitState

Returns a formatted payload for a stored SummitState.

function _formatSummitState(SummitState memory summitState) internal pure returns (bytes memory);

_toSummitState

Returns a SummitState struct to save in the contract.

function _toSummitState(State state, uint32 guardIndex) internal pure returns (SummitState memory summitState);

_formatSummitAttestation

Returns a formatted payload for a stored SummitAttestation.

function _formatSummitAttestation(SummitAttestation memory summitAtt, uint32 nonce)
    internal
    pure
    returns (bytes memory);

_toSummitAttestation

Returns an Attestation struct to save in the Summit contract. Current block number and timestamp are used.

function _toSummitAttestation(bytes32 snapRoot, bytes32 agentRoot, bytes32 snapGasHash)
    internal
    view
    returns (SummitAttestation memory summitAtt);

_areEqual

Checks that an Attestation and its Summit representation are equal.

function _areEqual(Attestation att, SummitAttestation memory summitAtt) internal pure returns (bool);

Structs

SummitState

Struct that represents stored State of Origin contract

struct SummitState {
    bytes32 root;
    uint32 origin;
    uint32 nonce;
    uint40 blockNumber;
    uint40 timestamp;
    GasData gasData;
    uint32 guardIndex;
    uint32 notaryIndex;
}

SummitSnapshot

struct SummitSnapshot {
    uint256[] statePtrs;
    uint256 sigIndex;
}

SummitAttestation

struct SummitAttestation {
    bytes32 snapRoot;
    bytes32 agentRoot;
    bytes32 snapGasHash;
    uint40 blockNumber;
    uint40 timestamp;
}

StateHub

Git Source

Inherits: AgentSecured, StateHubEvents, IStateHub

StateHub is a parent contract for Origin. It is responsible for the following:

  • Keeping track of the historical Origin Merkle Tree containing all the message hashes.
  • Keeping track of the historical Origin States, as well as verifying their validity.

State Variables

_tree

Historical Merkle Tree Note: Takes two storage slots

HistoricalTree private _tree;

_originStates

All historical contract States

OriginState[] private _originStates;

__GAP

gap for upgrade safety

uint256[47] private __GAP;

Functions

isValidState

Check that a given state is valid: matches the historical state of Origin contract. Note: any Agent including an invalid state in their snapshot will be slashed upon providing the snapshot and agent signature for it to Origin contract.

*Will revert if any of these is true:

  • State payload is not properly formatted.*
function isValidState(bytes memory statePayload) external view returns (bool isValid);

Parameters

NameTypeDescription
statePayloadbytesRaw payload with state data

Returns

NameTypeDescription
isValidboolWhether the provided state is valid

statesAmount

Returns the amount of saved states so far.

This includes the initial state of "empty Origin Merkle Tree".

function statesAmount() external view returns (uint256);

suggestLatestState

Suggest the data (state after latest sent message) to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain).

function suggestLatestState() external view returns (bytes memory stateData);

Returns

NameTypeDescription
stateDatabytesstatePayload Raw payload with the latest state data

suggestState

Given the historical nonce, suggest the state data to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain).

function suggestState(uint32 nonce) public view returns (bytes memory stateData);

Parameters

NameTypeDescription
nonceuint32Historical nonce to form a state

Returns

NameTypeDescription
stateDatabytesstatePayload Raw payload with historical state data

_initializeStates

Initializes the saved states list by inserting a state for an empty Merkle Tree.

function _initializeStates() internal;

_insertAndSave

Inserts leaf into the Merkle Tree and saves the updated origin State.

function _insertAndSave(bytes32 leaf) internal;

_saveState

Saves an updated state of the Origin contract

function _saveState(bytes32 root, OriginState memory state) internal;

_nextNonce

Returns nonce of the next sent message: the amount of saved States so far. This always equals to "total amount of sent messages" plus 1.

function _nextNonce() internal view returns (uint32);

_isValidState

Checks if a state is valid, i.e. if it matches the historical one. Reverts, if state refers to another Origin contract.

function _isValidState(State state) internal view returns (bool);

_formatOriginState

Returns a formatted payload for a stored OriginState.

function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)
    internal
    pure
    returns (bytes memory);

_fetchGasData

Child contract should implement the logic for getting the current gas data from the gas oracle to be saved as part of the Origin State.

function _fetchGasData() internal view virtual returns (GasData);

_toOriginState

Returns a OriginState struct to save in the contract.

function _toOriginState() internal view returns (OriginState memory originState);

_areEqual

Checks that a state and its Origin representation are equal.

function _areEqual(State state, OriginState memory originState) internal pure returns (bool);

Structs

OriginState

struct OriginState {
    uint40 blockNumber;
    uint40 timestamp;
    GasData gasData;
}

Contents

Inbox

Git Source

Inherits: StatementInbox, InboxEvents, InterfaceInbox

Inbox is the child of StatementInbox contract, that is used on Synapse Chain. In addition to the functionality of StatementInbox, it also:

  • Accepts Guard and Notary Snapshots and passes them to Summit contract.
  • Accepts Notary-signed Receipts and passes them to Summit contract.
  • Accepts Receipt Reports to initiate a dispute between Guard and Notary.
  • Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.

State Variables

summit

address public summit;

Functions

constructor

constructor(uint32 synapseDomain_) MessagingBase("0.0.3", synapseDomain_);

initialize

Initializes Inbox contract:

  • Sets msg.sender as the owner of the contract
  • Sets agentManager, origin, destination and summit addresses
function initialize(address agentManager_, address origin_, address destination_, address summit_)
    external
    initializer;

submitSnapshot

Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.

Snapshot is a list of states for a set of Origin contracts residing on any of the chains.

  • Guard-signed snapshots: all the states in the snapshot become available for Notary signing.
  • Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e. snapshots which are only using states previously submitted by any of the Guards.
  • Notary doesn't have to use states submitted by a single Guard in their snapshot.
  • Notary could then proceed to sign the attestation for their submitted snapshot.

Will revert if any of these is true:

  • Snapshot payload is not properly formatted.
  • Snapshot signer is not an active Agent.
  • Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.
  • Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.
  • Note: Agent will NOT be slashed for submitting such a snapshot.

Notary will need to provide both agentRoot and snapGas when submitting an attestation on the remote chain (the attestation contains only their merged hash). These are returned by this function, and could be also obtained by calling getAttestation(nonce) or getLatestNotaryAttestation(notary).

function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)
    external
    returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas);

Parameters

NameTypeDescription
snapPayloadbytesRaw payload with snapshot data
snapSignaturebytesAgent signature for the snapshot

Returns

NameTypeDescription
attPayloadbytesRaw payload with data for attestation derived from Notary snapshot. Empty payload, if a Guard snapshot was submitted.
agentRoot_bytes32agentRoot Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)
snapGasuint256[]Gas data for each chain in the snapshot Empty list, if a Guard snapshot was submitted.

submitReceipt

Accepts a receipt signed by a Notary and passes it to Summit contract to save.

Receipt is a statement about message execution status on the remote chain.

  • This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.

Will revert if any of these is true:

  • Receipt payload is not properly formatted.
  • Receipt signer is not an active Notary.
  • Receipt signer is in Dispute.
  • Receipt's snapshot root is unknown.
  • Provided tips could not be proven against the message hash.
function submitReceipt(
    bytes memory rcptPayload,
    bytes memory rcptSignature,
    uint256 paddedTips,
    bytes32 headerHash,
    bytes32 bodyHash
) external returns (bool wasAccepted);

Parameters

NameTypeDescription
rcptPayloadbytesRaw payload with receipt data
rcptSignaturebytesNotary signature for the receipt
paddedTipsuint256Tips for the message execution
headerHashbytes32Hash of the message header
bodyHashbytes32Hash of the message body excluding the tips

Returns

NameTypeDescription
wasAcceptedboolWhether the receipt was accepted

submitReceiptReport

Accepts a Guard's receipt report signature, as well as Notary signature for the reported Receipt.

ReceiptReport is a Guard statement saying "Reported receipt is invalid".

  • This results in an opened Dispute between the Guard and the Notary.
  • Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from verifyReceipt() successful call that led to Notary being slashed in Summit on Synapse Chain.

Will revert if any of these is true:

  • Receipt payload is not properly formatted.
  • Receipt Report signer is not an active Guard.
  • Receipt signer is not an active Notary.
function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)
    external
    returns (bool wasAccepted);

Parameters

NameTypeDescription
rcptPayloadbytesRaw payload with Receipt data that Guard reports as invalid
rcptSignaturebytesNotary signature for the reported receipt
rrSignaturebytesGuard signature for the report

Returns

NameTypeDescription
wasAcceptedboolWhether the Report was accepted (resulting in Dispute between the agents)

passReceipt

Passes the message execution receipt from Destination to the Summit contract to save.

Will revert if any of these is true:

  • Called by anyone other than Destination.

If a receipt is not accepted, any of the Notaries can submit it later using submitReceipt.

function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)
    external
    returns (bool wasAccepted);

Parameters

NameTypeDescription
attNotaryIndexuint32Index of the Notary who signed the attestation
attNonceuint32Nonce of the attestation used for proving the executed message
paddedTipsuint256Tips for the message execution
rcptPayloadbytesRaw payload with message execution receipt

Returns

NameTypeDescription
wasAcceptedboolWhether the receipt was accepted

verifyAttestation

Verifies an attestation signed by a Notary.

  • Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).
  • Slashes the Notary, if the attestation is invalid.

Will revert if any of these is true:

  • Attestation payload is not properly formatted.
  • Attestation signer is not an active Notary.
function verifyAttestation(bytes memory attPayload, bytes memory attSignature)
    external
    returns (bool isValidAttestation);

Parameters

NameTypeDescription
attPayloadbytesRaw payload with Attestation data
attSignaturebytesNotary signature for the attestation

Returns

NameTypeDescription
isValidAttestationboolWhether the provided attestation is valid. Notary is slashed, if return value is FALSE.

verifyAttestationReport

Verifies a Guard's attestation report signature.

  • Does nothing, if the report is valid (if the reported attestation is invalid).
  • Slashes the Guard, if the report is invalid (if the reported attestation is valid).

Will revert if any of these is true:

  • Attestation payload is not properly formatted.
  • Attestation Report signer is not an active Guard.
function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)
    external
    returns (bool isValidReport);

Parameters

NameTypeDescription
attPayloadbytesRaw payload with Attestation data that Guard reports as invalid
arSignaturebytesGuard signature for the report

Returns

NameTypeDescription
isValidReportboolWhether the provided report is valid. Guard is slashed, if return value is FALSE.

_verifyReceiptTips

Verifies that tips proof matches the message hash.

function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash) internal pure;

Structs

ReceiptInfo

struct ReceiptInfo {
    AgentStatus rcptNotaryStatus;
    address notary;
    uint32 attNonce;
    AgentStatus attNotaryStatus;
}

LightInbox

Git Source

Inherits: StatementInbox, InterfaceLightInbox

LightInbox is the child of StatementInbox contract, that is used chains other than the Synapse Chain. In addition to the functionality of StatementInbox, it also:

  • Accepts Notary Attestations and passes them to the Destination contract.
  • Accepts Attestation Reports and initiates a dispute between the Notary and the Guard.

Functions

constructor

constructor(uint32 synapseDomain_) MessagingBase("0.0.3", synapseDomain_);

initialize

Initializes LightInbox contract:

  • Sets msg.sender as the owner of the contract
  • Sets agentManager, origin and destination addresses
function initialize(address agentManager_, address origin_, address destination_) external initializer;

submitAttestation

Accepts an attestation signed by a Notary and passes it to Destination contract to save.

Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.

  • Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.
  • Messages coming from chains included in the Attestation's snapshot could be proven.
  • Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.

Will revert if any of these is true:

  • Attestation payload is not properly formatted.
  • Attestation signer is not an active Notary for local domain.
  • Attestation signer is in Dispute.
  • Attestation's snapshot root has been previously submitted.
  • Attestation's data hash doesn't match the hash of provided agentRoot and snapshot gas data.
function submitAttestation(
    bytes memory attPayload,
    bytes memory attSignature,
    bytes32 agentRoot_,
    uint256[] memory snapGas_
) external returns (bool wasAccepted);

Parameters

NameTypeDescription
attPayloadbytesRaw payload with Attestation data
attSignaturebytesNotary signature for the attestation
agentRoot_bytes32
snapGas_uint256[]

Returns

NameTypeDescription
wasAcceptedboolWhether the Attestation was accepted

submitAttestationReport

Accepts a Guard's attestation report signature, as well as Notary signature for the reported Attestation.

AttestationReport is a Guard statement saying "Reported attestation is invalid".

  • This results in an opened Dispute between the Guard and the Notary.
  • Note: Guard could (but doesn't have to) form a AttestationReport and use attestation signature from verifyAttestation() successful call that led to Notary being slashed in Summit on Synapse Chain.

Will revert if any of these is true:

  • Attestation payload is not properly formatted.
  • Attestation Report signer is not an active Guard.
  • Attestation signer is not an active Notary for local domain.
function submitAttestationReport(bytes memory attPayload, bytes memory arSignature, bytes memory attSignature)
    external
    returns (bool wasAccepted);

Parameters

NameTypeDescription
attPayloadbytesRaw payload with Attestation data that Guard reports as invalid
arSignaturebytesGuard signature for the report
attSignaturebytesNotary signature for the reported attestation

Returns

NameTypeDescription
wasAcceptedboolWhether the Report was accepted (resulting in Dispute between the agents)

StatementInbox

Git Source

Inherits: MessagingBase, StatementInboxEvents, IStatementInbox

StatementInbox is the entry point for all agent-signed statements. It verifies the agent signatures, and passes the unsigned statements to the contract to consume it via acceptX functions. Is is also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid. StatementInbox is responsible for the following:

  • Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.
  • Storing all the Guard Reports with the Guard signature leading to a dispute.
  • Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.
  • Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.

State Variables

agentManager

address public agentManager;

origin

address public origin;

destination

address public destination;

_storedSignatures

bytes[] internal _storedSignatures;

_storedReports

StoredReport[] internal _storedReports;

__GAP

gap for upgrade safety

uint256[45] private __GAP;

Functions

__StatementInbox_init

*Initializes the contract:

  • Sets up msg.sender as the owner of the contract.
  • Sets up agentManager, origin, and destination.*
function __StatementInbox_init(address agentManager_, address origin_, address destination_)
    internal
    onlyInitializing;

submitStateReportWithSnapshot

Accepts a Guard's state report signature, a Snapshot containing the reported State, as well as Notary signature for the Snapshot.

StateReport is a Guard statement saying "Reported state is invalid".

  • This results in an opened Dispute between the Guard and the Notary.
  • Note: Guard could (but doesn't have to) form a StateReport and use other values from verifyStateWithSnapshot() successful call that led to Notary being slashed in remote Origin.

Will revert if any of these is true:

  • State Report signer is not an active Guard.
  • Snapshot payload is not properly formatted.
  • Snapshot signer is not an active Notary.
  • State index is out of range.
  • The Guard or the Notary are already in a Dispute
function submitStateReportWithSnapshot(
    uint8 stateIndex,
    bytes memory srSignature,
    bytes memory snapPayload,
    bytes memory snapSignature
) external returns (bool wasAccepted);

Parameters

NameTypeDescription
stateIndexuint8Index of the reported State in the Snapshot
srSignaturebytesGuard signature for the report
snapPayloadbytesRaw payload with Snapshot data
snapSignaturebytesNotary signature for the Snapshot

Returns

NameTypeDescription
wasAcceptedboolWhether the Report was accepted (resulting in Dispute between the agents)

submitStateReportWithAttestation

Accepts a Guard's state report signature, a Snapshot containing the reported State, as well as Notary signature for the Attestation created from this Snapshot.

StateReport is a Guard statement saying "Reported state is invalid".

  • This results in an opened Dispute between the Guard and the Notary.
  • Note: Guard could (but doesn't have to) form a StateReport and use other values from verifyStateWithAttestation() successful call that led to Notary being slashed in remote Origin.

Will revert if any of these is true:

  • State Report signer is not an active Guard.
  • Snapshot payload is not properly formatted.
  • State index is out of range.
  • Attestation payload is not properly formatted.
  • Attestation signer is not an active Notary.
  • Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.
  • The Guard or the Notary are already in a Dispute
function submitStateReportWithAttestation(
    uint8 stateIndex,
    bytes memory srSignature,
    bytes memory snapPayload,
    bytes memory attPayload,
    bytes memory attSignature
) external returns (bool wasAccepted);

Parameters

NameTypeDescription
stateIndexuint8Index of the reported State in the Snapshot
srSignaturebytesGuard signature for the report
snapPayloadbytesRaw payload with Snapshot data
attPayloadbytesRaw payload with Attestation data
attSignaturebytesNotary signature for the Attestation

Returns

NameTypeDescription
wasAcceptedboolWhether the Report was accepted (resulting in Dispute between the agents)

submitStateReportWithSnapshotProof

Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation, as well as Notary signature for the Attestation.

StateReport is a Guard statement saying "Reported state is invalid".

  • This results in an opened Dispute between the Guard and the Notary.
  • Note: Guard could (but doesn't have to) form a StateReport and use other values from verifyStateWithSnapshotProof() successful call that led to Notary being slashed in remote Origin.

Will revert if any of these is true:

  • State payload is not properly formatted.
  • State Report signer is not an active Guard.
  • Attestation payload is not properly formatted.
  • Attestation signer is not an active Notary.
  • Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.
  • Snapshot Proof's first element does not match the State metadata.
  • Snapshot Proof length exceeds Snapshot Tree Height.
  • State index is out of range.
  • The Guard or the Notary are already in a Dispute
function submitStateReportWithSnapshotProof(
    uint8 stateIndex,
    bytes memory statePayload,
    bytes memory srSignature,
    bytes32[] memory snapProof,
    bytes memory attPayload,
    bytes memory attSignature
) external returns (bool wasAccepted);

Parameters

NameTypeDescription
stateIndexuint8Index of the reported State in the Snapshot
statePayloadbytesRaw payload with State data that Guard reports as invalid
srSignaturebytesGuard signature for the report
snapProofbytes32[]Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree
attPayloadbytesRaw payload with Attestation data
attSignaturebytesNotary signature for the Attestation

Returns

NameTypeDescription
wasAcceptedboolWhether the Report was accepted (resulting in Dispute between the agents)

verifyReceipt

Verifies a message receipt signed by the Notary.

  • Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).
  • Slashes the Notary, if the receipt is invalid.

Will revert if any of these is true:

  • Receipt payload is not properly formatted.
  • Receipt signer is not an active Notary.
  • Receipt's destination chain does not refer to this chain.
function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature) external returns (bool isValidReceipt);

Parameters

NameTypeDescription
rcptPayloadbytesRaw payload with Receipt data
rcptSignaturebytesNotary signature for the receipt

Returns

NameTypeDescription
isValidReceiptboolWhether the provided receipt is valid. Notary is slashed, if return value is FALSE.

verifyReceiptReport

Verifies a Guard's receipt report signature.

  • Does nothing, if the report is valid (if the reported receipt is invalid).
  • Slashes the Guard, if the report is invalid (if the reported receipt is valid).

Will revert if any of these is true:

  • Receipt payload is not properly formatted.
  • Receipt Report signer is not an active Guard.
  • Receipt does not refer to this chain.
function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)
    external
    returns (bool isValidReport);

Parameters

NameTypeDescription
rcptPayloadbytesRaw payload with Receipt data that Guard reports as invalid
rrSignaturebytesGuard signature for the report

Returns

NameTypeDescription
isValidReportboolWhether the provided report is valid. Guard is slashed, if return value is FALSE.

verifyStateWithAttestation

Verifies a state from the snapshot, that was used for the Notary-signed attestation.

  • Does nothing, if the state is valid (matches the historical state of this contract).
  • Slashes the Notary, if the state is invalid.

Will revert if any of these is true:

  • Attestation payload is not properly formatted.
  • Attestation signer is not an active Notary.
  • Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.
  • Snapshot payload is not properly formatted.
  • State index is out of range.
  • State does not refer to this chain.
function verifyStateWithAttestation(
    uint8 stateIndex,
    bytes memory snapPayload,
    bytes memory attPayload,
    bytes memory attSignature
) external returns (bool isValidState);

Parameters

NameTypeDescription
stateIndexuint8State index to check
snapPayloadbytesRaw payload with snapshot data
attPayloadbytesRaw payload with Attestation data
attSignaturebytesNotary signature for the attestation

Returns

NameTypeDescription
isValidStateboolWhether the provided state is valid. Notary is slashed, if return value is FALSE.

verifyStateWithSnapshotProof

Verifies a state from the snapshot, that was used for the Notary-signed attestation.

  • Does nothing, if the state is valid (matches the historical state of this contract).
  • Slashes the Notary, if the state is invalid.

Will revert if any of these is true:

  • Attestation payload is not properly formatted.
  • Attestation signer is not an active Notary.
  • Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.
  • Snapshot Proof's first element does not match the State metadata.
  • Snapshot Proof length exceeds Snapshot Tree Height.
  • State payload is not properly formatted.
  • State index is out of range.
  • State does not refer to this chain.
function verifyStateWithSnapshotProof(
    uint8 stateIndex,
    bytes memory statePayload,
    bytes32[] memory snapProof,
    bytes memory attPayload,
    bytes memory attSignature
) external returns (bool isValidState);

Parameters

NameTypeDescription
stateIndexuint8Index of state in the snapshot
statePayloadbytesRaw payload with State data to check
snapProofbytes32[]Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree
attPayloadbytesRaw payload with Attestation data
attSignaturebytesNotary signature for the attestation

Returns

NameTypeDescription
isValidStateboolWhether the provided state is valid. Notary is slashed, if return value is FALSE.

verifyStateWithSnapshot

Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.

  • Does nothing, if the state is valid (matches the historical state of this contract).
  • Slashes the Agent, if the state is invalid.

Will revert if any of these is true:

  • Snapshot payload is not properly formatted.
  • Snapshot signer is not an active Agent.
  • State index is out of range.
  • State does not refer to this chain.
function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)
    external
    returns (bool isValidState);

Parameters

NameTypeDescription
stateIndexuint8State index to check
snapPayloadbytesRaw payload with snapshot data
snapSignaturebytesAgent signature for the snapshot

Returns

NameTypeDescription
isValidStateboolWhether the provided state is valid. Agent is slashed, if return value is FALSE.

verifyStateReport

Verifies a Guard's state report signature.

  • Does nothing, if the report is valid (if the reported state is invalid).
  • Slashes the Guard, if the report is invalid (if the reported state is valid).

Will revert if any of these is true:

  • State payload is not properly formatted.
  • State Report signer is not an active Guard.
  • Reported State does not refer to this chain.
function verifyStateReport(bytes memory statePayload, bytes memory srSignature) external returns (bool isValidReport);

Parameters

NameTypeDescription
statePayloadbytesRaw payload with State data that Guard reports as invalid
srSignaturebytesGuard signature for the report

Returns

NameTypeDescription
isValidReportboolWhether the provided report is valid. Guard is slashed, if return value is FALSE.

getReportsAmount

Returns the amount of Guard Reports stored in StatementInbox.

Only reports that led to opening a Dispute are stored.

function getReportsAmount() external view returns (uint256);

getGuardReport

Returns the Guard report with the given index stored in StatementInbox.

Only reports that led to opening a Dispute are stored.

Will revert if report with given index doesn't exist.

function getGuardReport(uint256 index)
    external
    view
    returns (bytes memory statementPayload, bytes memory reportSignature);

Parameters

NameTypeDescription
indexuint256Report index

Returns

NameTypeDescription
statementPayloadbytesRaw payload with statement that Guard reported as invalid
reportSignaturebytesGuard signature for the report

getStoredSignature

Returns the signature with the given index stored in StatementInbox.

Will revert if signature with given index doesn't exist.

function getStoredSignature(uint256 index) external view returns (bytes memory);

Parameters

NameTypeDescription
indexuint256Signature index

Returns

NameTypeDescription
<none>bytesRaw payload with signature

_saveReport

Saves the statement reported by Guard as invalid and the Guard Report signature.

function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal;

_saveSignature

Saves the signature and returns its index.

function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex);

_recoverAgent

Recovers a signer from a hashed message, and a EIP-191 signature for it. Will revert, if the signer is not a known agent.

Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed Further checks need to be performed in a caller function.

function _recoverAgent(bytes32 hashedStatement, bytes memory signature)
    internal
    view
    returns (AgentStatus memory status, address agent);

Parameters

NameTypeDescription
hashedStatementbytes32Hash of the statement that was signed by an Agent
signaturebytesAgent signature for the hashed statement

Returns

NameTypeDescription
statusAgentStatusStruct representing agent status: - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed - domain Domain where agent is/was active - index Index of agent in the Agent Merkle Tree
agentaddressAgent that signed the statement

_verifyNotaryDomain

Verifies that Notary signature is active on local domain.

function _verifyNotaryDomain(uint32 notaryDomain) internal view;

_verifyAttestation

*Internal function to verify the signed attestation payload. Reverts if any of these is true:

  • Attestation signer is not a known Notary.*
function _verifyAttestation(Attestation att, bytes memory attSignature)
    internal
    view
    returns (AgentStatus memory status, address notary);

Parameters

NameTypeDescription
attAttestationTyped memory view over attestation payload
attSignaturebytesNotary signature for the attestation

Returns

NameTypeDescription
statusAgentStatusStruct representing agent status, see {_recoverAgent}
notaryaddressNotary that signed the snapshot

_verifyAttestationReport

*Internal function to verify the signed attestation report payload. Reverts if any of these is true:

  • Report signer is not a known Guard.*
function _verifyAttestationReport(Attestation att, bytes memory arSignature)
    internal
    view
    returns (AgentStatus memory status, address guard);

Parameters

NameTypeDescription
attAttestationTyped memory view over attestation payload that Guard reports as invalid
arSignaturebytesGuard signature for the "invalid attestation" report

Returns

NameTypeDescription
statusAgentStatusStruct representing guard status, see {_recoverAgent}
guardaddressGuard that signed the report

_verifyReceipt

*Internal function to verify the signed receipt payload. Reverts if any of these is true:

  • Receipt signer is not a known Notary.*
function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)
    internal
    view
    returns (AgentStatus memory status, address notary);

Parameters

NameTypeDescription
rcptReceiptTyped memory view over receipt payload
rcptSignaturebytesNotary signature for the receipt

Returns

NameTypeDescription
statusAgentStatusStruct representing agent status, see {_recoverAgent}
notaryaddressNotary that signed the snapshot

_verifyReceiptReport

*Internal function to verify the signed receipt report payload. Reverts if any of these is true:

  • Report signer is not a known Guard.*
function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)
    internal
    view
    returns (AgentStatus memory status, address guard);

Parameters

NameTypeDescription
rcptReceiptTyped memory view over receipt payload that Guard reports as invalid
rrSignaturebytesGuard signature for the "invalid receipt" report

Returns

NameTypeDescription
statusAgentStatusStruct representing guard status, see {_recoverAgent}
guardaddressGuard that signed the report

_verifyStateReport

*Internal function to verify the signed snapshot report payload. Reverts if any of these is true:

  • Report signer is not a known Guard.*
function _verifyStateReport(State state, bytes memory srSignature)
    internal
    view
    returns (AgentStatus memory status, address guard);

Parameters

NameTypeDescription
stateStateTyped memory view over state payload that Guard reports as invalid
srSignaturebytesGuard signature for the report

Returns

NameTypeDescription
statusAgentStatusStruct representing guard status, see {_recoverAgent}
guardaddressGuard that signed the report

_verifySnapshot

*Internal function to verify the signed snapshot payload. Reverts if any of these is true:

  • Snapshot signer is not a known Agent.
  • Snapshot signer is not a Notary (if verifyNotary is true).*
function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)
    internal
    view
    returns (AgentStatus memory status, address agent);

Parameters

NameTypeDescription
snapshotSnapshotTyped memory view over snapshot payload
snapSignaturebytesAgent signature for the snapshot
verifyNotaryboolIf true, snapshot signer needs to be a Notary, not a Guard

Returns

NameTypeDescription
statusAgentStatusStruct representing agent status, see {_recoverAgent}
agentaddressAgent that signed the snapshot

_verifySnapshotMerkle

*Internal function to verify that snapshot roots match. Reverts if any of these is true:

  • Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.
  • Snapshot Proof's first element does not match the State metadata.
  • Snapshot Proof length exceeds Snapshot tree Height.
  • State index is out of range.*
function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)
    internal
    pure;

Parameters

NameTypeDescription
attAttestationTyped memory view over Attestation
stateIndexuint8Index of state in the snapshot
stateStateTyped memory view over the provided state payload
snapProofbytes32[]Raw payload with snapshot data

Structs

StoredReport

struct StoredReport {
    uint256 sigIndex;
    bytes statementPayload;
}

Contents

IAgentManager

Git Source

Functions

openDispute

Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.

Will revert if any of these is true:

  • Caller is not Inbox.
  • Guard or Notary is already in Dispute.
function openDispute(uint32 guardIndex, uint32 notaryIndex) external;

Parameters

NameTypeDescription
guardIndexuint32Index of the Guard in the Agent Merkle Tree
notaryIndexuint32Index of the Notary in the Agent Merkle Tree

slashAgent

Allows Inbox to slash an agent, if their fraud was proven.

Will revert if any of these is true:

  • Caller is not Inbox.
  • Domain doesn't match the saved agent domain.
function slashAgent(uint32 domain, address agent, address prover) external;

Parameters

NameTypeDescription
domainuint32Domain where the Agent is active
agentaddressAddress of the Agent
proveraddressAddress that initially provided fraud proof

agentRoot

Returns the latest known root of the Agent Merkle Tree.

function agentRoot() external view returns (bytes32);

agentStatus

Returns (flag, domain, index) for a given agent. See Structures.sol for details.

Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.

function agentStatus(address agent) external view returns (AgentStatus memory);

Parameters

NameTypeDescription
agentaddressAgent address

Returns

NameTypeDescription
<none>AgentStatusStatus for the given agent: (flag, domain, index).

getAgent

Returns agent address and their current status for a given agent index.

Will return empty values if agent with given index doesn't exist.

function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);

Parameters

NameTypeDescription
indexuint256Agent index in the Agent Merkle Tree

Returns

NameTypeDescription
agentaddressAgent address
statusAgentStatusStatus for the given agent: (flag, domain, index)

getDisputesAmount

Returns the number of opened Disputes.

This includes the Disputes that have been resolved already.

function getDisputesAmount() external view returns (uint256);

getDispute

Returns information about the dispute with the given index.

Will revert if dispute with given index hasn't been opened yet.

function getDispute(uint256 index)
    external
    view
    returns (
        address guard,
        address notary,
        address slashedAgent,
        address fraudProver,
        bytes memory reportPayload,
        bytes memory reportSignature
    );

Parameters

NameTypeDescription
indexuint256Dispute index

Returns

NameTypeDescription
guardaddressAddress of the Guard in the Dispute
notaryaddressAddress of the Notary in the Dispute
slashedAgentaddressAddress of the Agent who was slashed when Dispute was resolved
fraudProveraddressAddress who provided fraud proof to resolve the Dispute
reportPayloadbytesRaw payload with report data that led to the Dispute
reportSignaturebytesGuard signature for the report payload

disputeStatus

Returns the current Dispute status of a given agent. See Structures.sol for details.

Every returned value will be set to zero if agent was not slashed and is not in Dispute. rival and disputePtr will be set to zero if the agent was slashed without being in Dispute.

function disputeStatus(address agent)
    external
    view
    returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);

Parameters

NameTypeDescription
agentaddressAgent address

Returns

NameTypeDescription
flagDisputeFlagFlag describing the current Dispute status for the agent: None/Pending/Slashed
rivaladdressAddress of the rival agent in the Dispute
fraudProveraddressAddress who provided fraud proof to resolve the Dispute
disputePtruint256Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.

IAgentSecured

Git Source

Functions

openDispute

Local AgentManager should call this function to indicate that a dispute between a Guard and a Notary has been opened.

function openDispute(uint32 guardIndex, uint32 notaryIndex) external;

Parameters

NameTypeDescription
guardIndexuint32Index of the Guard in the Agent Merkle Tree
notaryIndexuint32Index of the Notary in the Agent Merkle Tree

resolveDispute

Local AgentManager should call this function to indicate that a dispute has been resolved due to one of the agents being slashed.

rivalIndex will be ZERO, if the slashed agent was not in the Dispute.

function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;

Parameters

NameTypeDescription
slashedIndexuint32Index of the slashed agent in the Agent Merkle Tree
rivalIndexuint32Index of the their Dispute Rival in the Agent Merkle Tree

agentManager

Returns the address of the local AgentManager contract, which is treated as the "source of truth" for agent statuses.

function agentManager() external view returns (address);

inbox

Returns the address of the local Inbox contract, which is treated as the "source of truth" for agent-signed statements.

Inbox passes verified agent statements to IAgentSecured contract.

function inbox() external view returns (address);

agentStatus

Returns (flag, domain, index) for a given agent. See Structures.sol for details.

Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.

function agentStatus(address agent) external view returns (AgentStatus memory);

Parameters

NameTypeDescription
agentaddressAgent address

Returns

NameTypeDescription
<none>AgentStatusStatus for the given agent: (flag, domain, index).

getAgent

Returns agent address and their current status for a given agent index.

Will return empty values if agent with given index doesn't exist.

function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);

Parameters

NameTypeDescription
indexuint256Agent index in the Agent Merkle Tree

Returns

NameTypeDescription
agentaddressAgent address
statusAgentStatusStatus for the given agent: (flag, domain, index)

latestDisputeStatus

Returns (flag, openedAt, resolvedAt) that describes the latest status of the latest dispute for an agent with a given index.

Will return empty values if agent with given index doesn't exist.

function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);

Parameters

NameTypeDescription
agentIndexuint32Agent index in the Agent Merkle Tree

Returns

NameTypeDescription
<none>DisputeStatusLatest dispute status for the given agent: (flag, openedAt, resolvedAt)

IExecutionHub

Git Source

Functions

execute

Attempts to prove inclusion of message into one of Snapshot Merkle Trees, previously submitted to this contract in a form of a signed Attestation. Proven message is immediately executed by passing its contents to the specified recipient.

*Will revert if any of these is true:

  • Message is not meant to be executed on this chain
  • Message was sent from this chain
  • Message payload is not properly formatted.
  • Snapshot root (reconstructed from message hash and proofs) is unknown
  • Snapshot root is known, but was submitted by an inactive Notary
  • Snapshot root is known, but optimistic period for a message hasn't passed
  • Provided gas limit is lower than the one requested in the message
  • Recipient doesn't implement a handle method (refer to IMessageRecipient.sol)
  • Recipient reverted upon receiving a message Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.*
function execute(
    bytes memory msgPayload,
    bytes32[] calldata originProof,
    bytes32[] calldata snapProof,
    uint8 stateIndex,
    uint64 gasLimit
) external;

Parameters

NameTypeDescription
msgPayloadbytesRaw payload with a formatted message to execute
originProofbytes32[]Proof of inclusion of message in the Origin Merkle Tree
snapProofbytes32[]Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree
stateIndexuint8Index of Origin State in the Snapshot
gasLimituint64Gas limit for message execution

getAttestationNonce

Returns attestation nonce for a given snapshot root.

Will return 0 if the root is unknown.

function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);

isValidReceipt

Checks the validity of the unsigned message receipt.

*Will revert if any of these is true:

  • Receipt payload is not properly formatted.
  • Receipt signer is not an active Notary.
  • Receipt destination chain does not refer to this chain.*
function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);

Parameters

NameTypeDescription
rcptPayloadbytesRaw payload with Receipt data

Returns

NameTypeDescription
isValidboolWhether the requested receipt is valid.

messageStatus

Returns message execution status: None/Failed/Success.

function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);

Parameters

NameTypeDescription
messageHashbytes32Hash of the message payload

Returns

NameTypeDescription
statusMessageStatusMessage execution status

messageReceipt

Returns a formatted payload with the message receipt.

Notaries could derive the tips, and the tips proof using the message payload, and submit the signed receipt with the proof of tips to Summit in order to initiate tips distribution.

function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);

Parameters

NameTypeDescription
messageHashbytes32Hash of the message payload

Returns

NameTypeDescription
databytesFormatted payload with the message execution receipt

IMessageRecipient

Git Source

Functions

receiveBaseMessage

Message recipient needs to implement this function in order to receive cross-chain messages.

Message recipient needs to ensure that merkle proof for the message is at least as old as the optimistic period that the recipient is using. Note: as this point it is checked that the "message optimistic period" has passed, however the period value itself could be anything, and thus could differ from the one that the recipient would like to enforce.

function receiveBaseMessage(
    uint32 origin,
    uint32 nonce,
    bytes32 sender,
    uint256 proofMaturity,
    uint32 version,
    bytes memory content
) external payable;

Parameters

NameTypeDescription
originuint32Domain where message originated
nonceuint32Message nonce on the origin domain
senderbytes32Sender address on origin chain
proofMaturityuint256Message's merkle proof age in seconds
versionuint32Message version specified by sender
contentbytesRaw bytes content of message

ISnapshotHub

Git Source

Functions

isValidAttestation

Check that a given attestation is valid: matches the historical attestation derived from an accepted Notary snapshot.

*Will revert if any of these is true:

  • Attestation payload is not properly formatted.*
function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);

Parameters

NameTypeDescription
attPayloadbytesRaw payload with attestation data

Returns

NameTypeDescription
isValidboolWhether the provided attestation is valid

getAttestation

Returns saved attestation with the given nonce.

Reverts if attestation with given nonce hasn't been created yet.

function getAttestation(uint32 attNonce)
    external
    view
    returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);

Parameters

NameTypeDescription
attNonceuint32Nonce for the attestation

Returns

NameTypeDescription
attPayloadbytesRaw payload with formatted Attestation data
agentRootbytes32Agent root hash used for the attestation
snapGasuint256[]Snapshot gas data used for the attestation

getLatestAgentState

Returns the state with the highest known nonce submitted by a given Agent.

function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);

Parameters

NameTypeDescription
originuint32Domain of origin chain
agentaddressAgent address

Returns

NameTypeDescription
statePayloadbytesRaw payload with agent's latest state for origin

getLatestNotaryAttestation

Returns latest saved attestation for a Notary.

function getLatestNotaryAttestation(address notary)
    external
    view
    returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);

Parameters

NameTypeDescription
notaryaddressNotary address

Returns

NameTypeDescription
attPayloadbytesRaw payload with formatted Attestation data
agentRootbytes32Agent root hash used for the attestation
snapGasuint256[]Snapshot gas data used for the attestation

getGuardSnapshot

Returns Guard snapshot from the list of all accepted Guard snapshots.

Reverts if snapshot with given index hasn't been accepted yet.

function getGuardSnapshot(uint256 index) external view returns (bytes memory snapPayload, bytes memory snapSignature);

Parameters

NameTypeDescription
indexuint256Snapshot index in the list of all Guard snapshots

Returns

NameTypeDescription
snapPayloadbytesRaw payload with Guard snapshot
snapSignaturebytesRaw payload with Guard signature for snapshot

getNotarySnapshot

Returns Notary snapshot from the list of all accepted Guard snapshots.

Reverts if snapshot with given index hasn't been accepted yet.

function getNotarySnapshot(uint256 index)
    external
    view
    returns (bytes memory snapPayload, bytes memory snapSignature);

Parameters

NameTypeDescription
indexuint256Snapshot index in the list of all Notary snapshots

Returns

NameTypeDescription
snapPayloadbytesRaw payload with Notary snapshot
snapSignaturebytesRaw payload with Notary signature for snapshot

getNotarySnapshot

Returns Notary snapshot that was used for creating a given attestation.

*Reverts if any of these is true:

  • Attestation payload is not properly formatted.
  • Attestation is invalid (doesn't have a matching Notary snapshot).*
function getNotarySnapshot(bytes memory attPayload)
    external
    view
    returns (bytes memory snapPayload, bytes memory snapSignature);

Parameters

NameTypeDescription
attPayloadbytesRaw payload with attestation data

Returns

NameTypeDescription
snapPayloadbytesRaw payload with Notary snapshot
snapSignaturebytesRaw payload with Notary signature for snapshot

getSnapshotProof

Returns proof of inclusion of (root, origin) fields of a given snapshot's state into the Snapshot Merkle Tree for a given attestation.

*Reverts if any of these is true:

  • Attestation with given nonce hasn't been created yet.
  • State index is out of range of snapshot list.*
function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);

Parameters

NameTypeDescription
attNonceuint32Nonce for the attestation
stateIndexuint8Index of state in the attestation's snapshot

Returns

NameTypeDescription
snapProofbytes32[]The snapshot proof

IStateHub

Git Source

Functions

isValidState

Check that a given state is valid: matches the historical state of Origin contract. Note: any Agent including an invalid state in their snapshot will be slashed upon providing the snapshot and agent signature for it to Origin contract.

*Will revert if any of these is true:

  • State payload is not properly formatted.*
function isValidState(bytes memory statePayload) external view returns (bool isValid);

Parameters

NameTypeDescription
statePayloadbytesRaw payload with state data

Returns

NameTypeDescription
isValidboolWhether the provided state is valid

statesAmount

Returns the amount of saved states so far.

This includes the initial state of "empty Origin Merkle Tree".

function statesAmount() external view returns (uint256);

suggestLatestState

Suggest the data (state after latest sent message) to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain).

function suggestLatestState() external view returns (bytes memory statePayload);

Returns

NameTypeDescription
statePayloadbytesRaw payload with the latest state data

suggestState

Given the historical nonce, suggest the state data to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain).

function suggestState(uint32 nonce) external view returns (bytes memory statePayload);

Parameters

NameTypeDescription
nonceuint32Historical nonce to form a state

Returns

NameTypeDescription
statePayloadbytesRaw payload with historical state data

IStatementInbox

Git Source

Functions

submitStateReportWithSnapshot

Accepts a Guard's state report signature, a Snapshot containing the reported State, as well as Notary signature for the Snapshot.

StateReport is a Guard statement saying "Reported state is invalid".

  • This results in an opened Dispute between the Guard and the Notary.
  • Note: Guard could (but doesn't have to) form a StateReport and use other values from verifyStateWithSnapshot() successful call that led to Notary being slashed in remote Origin.

Will revert if any of these is true:

  • State Report signer is not an active Guard.
  • Snapshot payload is not properly formatted.
  • Snapshot signer is not an active Notary.
  • State index is out of range.
  • The Guard or the Notary are already in a Dispute
function submitStateReportWithSnapshot(
    uint8 stateIndex,
    bytes memory srSignature,
    bytes memory snapPayload,
    bytes memory snapSignature
) external returns (bool wasAccepted);

Parameters

NameTypeDescription
stateIndexuint8Index of the reported State in the Snapshot
srSignaturebytesGuard signature for the report
snapPayloadbytesRaw payload with Snapshot data
snapSignaturebytesNotary signature for the Snapshot

Returns

NameTypeDescription
wasAcceptedboolWhether the Report was accepted (resulting in Dispute between the agents)

submitStateReportWithAttestation

Accepts a Guard's state report signature, a Snapshot containing the reported State, as well as Notary signature for the Attestation created from this Snapshot.

StateReport is a Guard statement saying "Reported state is invalid".

  • This results in an opened Dispute between the Guard and the Notary.
  • Note: Guard could (but doesn't have to) form a StateReport and use other values from verifyStateWithAttestation() successful call that led to Notary being slashed in remote Origin.

Will revert if any of these is true:

  • State Report signer is not an active Guard.
  • Snapshot payload is not properly formatted.
  • State index is out of range.
  • Attestation payload is not properly formatted.
  • Attestation signer is not an active Notary.
  • Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.
  • The Guard or the Notary are already in a Dispute
function submitStateReportWithAttestation(
    uint8 stateIndex,
    bytes memory srSignature,
    bytes memory snapPayload,
    bytes memory attPayload,
    bytes memory attSignature
) external returns (bool wasAccepted);

Parameters

NameTypeDescription
stateIndexuint8Index of the reported State in the Snapshot
srSignaturebytesGuard signature for the report
snapPayloadbytesRaw payload with Snapshot data
attPayloadbytesRaw payload with Attestation data
attSignaturebytesNotary signature for the Attestation

Returns

NameTypeDescription
wasAcceptedboolWhether the Report was accepted (resulting in Dispute between the agents)

submitStateReportWithSnapshotProof

Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation, as well as Notary signature for the Attestation.

StateReport is a Guard statement saying "Reported state is invalid".

  • This results in an opened Dispute between the Guard and the Notary.
  • Note: Guard could (but doesn't have to) form a StateReport and use other values from verifyStateWithSnapshotProof() successful call that led to Notary being slashed in remote Origin.

Will revert if any of these is true:

  • State payload is not properly formatted.
  • State Report signer is not an active Guard.
  • Attestation payload is not properly formatted.
  • Attestation signer is not an active Notary.
  • Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.
  • Snapshot Proof's first element does not match the State metadata.
  • Snapshot Proof length exceeds Snapshot Tree Height.
  • State index is out of range.
  • The Guard or the Notary are already in a Dispute
function submitStateReportWithSnapshotProof(
    uint8 stateIndex,
    bytes memory statePayload,
    bytes memory srSignature,
    bytes32[] memory snapProof,
    bytes memory attPayload,
    bytes memory attSignature
) external returns (bool wasAccepted);

Parameters

NameTypeDescription
stateIndexuint8Index of the reported State in the Snapshot
statePayloadbytesRaw payload with State data that Guard reports as invalid
srSignaturebytesGuard signature for the report
snapProofbytes32[]Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree
attPayloadbytesRaw payload with Attestation data
attSignaturebytesNotary signature for the Attestation

Returns

NameTypeDescription
wasAcceptedboolWhether the Report was accepted (resulting in Dispute between the agents)

verifyReceipt

Verifies a message receipt signed by the Notary.

  • Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).
  • Slashes the Notary, if the receipt is invalid.

Will revert if any of these is true:

  • Receipt payload is not properly formatted.
  • Receipt signer is not an active Notary.
  • Receipt's destination chain does not refer to this chain.
function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature) external returns (bool isValidReceipt);

Parameters

NameTypeDescription
rcptPayloadbytesRaw payload with Receipt data
rcptSignaturebytesNotary signature for the receipt

Returns

NameTypeDescription
isValidReceiptboolWhether the provided receipt is valid. Notary is slashed, if return value is FALSE.

verifyReceiptReport

Verifies a Guard's receipt report signature.

  • Does nothing, if the report is valid (if the reported receipt is invalid).
  • Slashes the Guard, if the report is invalid (if the reported receipt is valid).

Will revert if any of these is true:

  • Receipt payload is not properly formatted.
  • Receipt Report signer is not an active Guard.
  • Receipt does not refer to this chain.
function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)
    external
    returns (bool isValidReport);

Parameters

NameTypeDescription
rcptPayloadbytesRaw payload with Receipt data that Guard reports as invalid
rrSignaturebytesGuard signature for the report

Returns

NameTypeDescription
isValidReportboolWhether the provided report is valid. Guard is slashed, if return value is FALSE.

verifyStateWithAttestation

Verifies a state from the snapshot, that was used for the Notary-signed attestation.

  • Does nothing, if the state is valid (matches the historical state of this contract).
  • Slashes the Notary, if the state is invalid.

Will revert if any of these is true:

  • Attestation payload is not properly formatted.
  • Attestation signer is not an active Notary.
  • Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.
  • Snapshot payload is not properly formatted.
  • State index is out of range.
  • State does not refer to this chain.
function verifyStateWithAttestation(
    uint8 stateIndex,
    bytes memory snapPayload,
    bytes memory attPayload,
    bytes memory attSignature
) external returns (bool isValidState);

Parameters

NameTypeDescription
stateIndexuint8State index to check
snapPayloadbytesRaw payload with snapshot data
attPayloadbytesRaw payload with Attestation data
attSignaturebytesNotary signature for the attestation

Returns

NameTypeDescription
isValidStateboolWhether the provided state is valid. Notary is slashed, if return value is FALSE.

verifyStateWithSnapshotProof

Verifies a state from the snapshot, that was used for the Notary-signed attestation.

  • Does nothing, if the state is valid (matches the historical state of this contract).
  • Slashes the Notary, if the state is invalid.

Will revert if any of these is true:

  • Attestation payload is not properly formatted.
  • Attestation signer is not an active Notary.
  • Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.
  • Snapshot Proof's first element does not match the State metadata.
  • Snapshot Proof length exceeds Snapshot Tree Height.
  • State payload is not properly formatted.
  • State index is out of range.
  • State does not refer to this chain.
function verifyStateWithSnapshotProof(
    uint8 stateIndex,
    bytes memory statePayload,
    bytes32[] memory snapProof,
    bytes memory attPayload,
    bytes memory attSignature
) external returns (bool isValidState);

Parameters

NameTypeDescription
stateIndexuint8Index of state in the snapshot
statePayloadbytesRaw payload with State data to check
snapProofbytes32[]Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree
attPayloadbytesRaw payload with Attestation data
attSignaturebytesNotary signature for the attestation

Returns

NameTypeDescription
isValidStateboolWhether the provided state is valid. Notary is slashed, if return value is FALSE.

verifyStateWithSnapshot

Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.

  • Does nothing, if the state is valid (matches the historical state of this contract).
  • Slashes the Agent, if the state is invalid.

Will revert if any of these is true:

  • Snapshot payload is not properly formatted.
  • Snapshot signer is not an active Agent.
  • State index is out of range.
  • State does not refer to this chain.
function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)
    external
    returns (bool isValidState);

Parameters

NameTypeDescription
stateIndexuint8State index to check
snapPayloadbytesRaw payload with snapshot data
snapSignaturebytesAgent signature for the snapshot

Returns

NameTypeDescription
isValidStateboolWhether the provided state is valid. Agent is slashed, if return value is FALSE.

verifyStateReport

Verifies a Guard's state report signature.

  • Does nothing, if the report is valid (if the reported state is invalid).
  • Slashes the Guard, if the report is invalid (if the reported state is valid).

Will revert if any of these is true:

  • State payload is not properly formatted.
  • State Report signer is not an active Guard.
  • Reported State does not refer to this chain.
function verifyStateReport(bytes memory statePayload, bytes memory srSignature) external returns (bool isValidReport);

Parameters

NameTypeDescription
statePayloadbytesRaw payload with State data that Guard reports as invalid
srSignaturebytesGuard signature for the report

Returns

NameTypeDescription
isValidReportboolWhether the provided report is valid. Guard is slashed, if return value is FALSE.

getReportsAmount

Returns the amount of Guard Reports stored in StatementInbox.

Only reports that led to opening a Dispute are stored.

function getReportsAmount() external view returns (uint256);

getGuardReport

Returns the Guard report with the given index stored in StatementInbox.

Only reports that led to opening a Dispute are stored.

Will revert if report with given index doesn't exist.

function getGuardReport(uint256 index)
    external
    view
    returns (bytes memory statementPayload, bytes memory reportSignature);

Parameters

NameTypeDescription
indexuint256Report index

Returns

NameTypeDescription
statementPayloadbytesRaw payload with statement that Guard reported as invalid
reportSignaturebytesGuard signature for the report

getStoredSignature

Returns the signature with the given index stored in StatementInbox.

Will revert if signature with given index doesn't exist.

function getStoredSignature(uint256 index) external view returns (bytes memory);

Parameters

NameTypeDescription
indexuint256Signature index

Returns

NameTypeDescription
<none>bytesRaw payload with signature

InterfaceBondingManager

Git Source

Functions

addAgent

Adds a new agent for the domain. This is either a fresh address (Inactive), or an agent who used to be active on the same domain before (Resting).

Inactive: proof should be the proof of inclusion of an empty leaf having index following the last added agent in the tree.

Resting: proof should be the proof of inclusion of the agent leaf with Resting flag having index previously assigned to the agent.

function addAgent(uint32 domain, address agent, bytes32[] memory proof) external;

Parameters

NameTypeDescription
domainuint32Domain where the Agent will be active
agentaddressAddress of the Agent
proofbytes32[]Merkle proof of the Inactive/Resting status for the agent

initiateUnstaking

Initiates the unstaking of the agent bond. Agent signature is immediately no longer considered valid on Synapse Chain, and will be invalid on other chains once the Light Manager updates their agent merkle root on these chains.

proof should be the proof of inclusion of the agent leaf with Active flag having index previously assigned to the agent.

function initiateUnstaking(uint32 domain, address agent, bytes32[] memory proof) external;

Parameters

NameTypeDescription
domainuint32Domain where the Agent is active
agentaddressAddress of the Agent
proofbytes32[]Merkle proof of the Active status for the agent

completeUnstaking

Completes the unstaking of the agent bond. Agent signature is no longer considered valid on any of the chains.

proof should be the proof of inclusion of the agent leaf with Unstaking flag having index previously assigned to the agent.

function completeUnstaking(uint32 domain, address agent, bytes32[] memory proof) external;

Parameters

NameTypeDescription
domainuint32Domain where the Agent was active
agentaddressAddress of the Agent
proofbytes32[]Merkle proof of the unstaking status for the agent

completeSlashing

Completes the slashing of the agent bond. Agent signature is no longer considered valid under the updated Agent Merkle Root.

proof should be the proof of inclusion of the agent leaf with Active/Unstaking flag having index previously assigned to the agent.

function completeSlashing(uint32 domain, address agent, bytes32[] memory proof) external;

Parameters

NameTypeDescription
domainuint32Domain where the Agent was active
agentaddressAddress of the Agent
proofbytes32[]Merkle proof of the active/unstaking status for the agent

remoteSlashAgent

Remote AgentManager should call this function to indicate that the agent has been proven to commit fraud on the origin chain.

This initiates the process of agent slashing. It could be immediately completed by anyone calling completeSlashing() providing a correct merkle proof for the OLD agent status. Note: as an extra security check this function returns its own selector, so that Destination could verify that a "remote" function was called when executing a manager message. Will revert if msgOrigin is equal to contract's local domain.

function remoteSlashAgent(uint32 msgOrigin, uint256 proofMaturity, uint32 domain, address agent, address prover)
    external
    returns (bytes4 magicValue);

Parameters

NameTypeDescription
msgOriginuint32
proofMaturityuint256
domainuint32Domain where the slashed agent was active
agentaddressAddress of the slashed Agent
proveraddressAddress that initially provided fraud proof to remote AgentManager

Returns

NameTypeDescription
magicValuebytes4Selector of this function

withdrawTips

Withdraws locked base message tips from requested domain Origin to the recipient. Issues a call to a local Origin contract, or sends a manager message to the remote chain.

Could only be called by the Summit contract.

function withdrawTips(address recipient, uint32 origin, uint256 amount) external;

Parameters

NameTypeDescription
recipientaddressAddress to withdraw tips to
originuint32Domain where tips need to be withdrawn
amountuint256Tips value to withdraw

resolveDisputeWhenStuck

Allows contract owner to resolve a stuck Dispute. This could only be called if no fresh data has been submitted by the Notaries to the Inbox, which is required for the Dispute to be resolved naturally.

Will revert if any of these is true:

  • Caller is not contract owner.
  • Domain doesn't match the saved agent domain.
  • slashedAgent is not in Dispute.
  • Less than FRESH_DATA_TIMEOUT has passed since the last Notary submission to the Inbox.
function resolveDisputeWhenStuck(uint32 domain, address slashedAgent) external;

Parameters

NameTypeDescription
domainuint32
slashedAgentaddressAgent that is being slashed

getActiveAgents

Returns all active agents for a given domain.

function getActiveAgents(uint32 domain) external view returns (address[] memory agents);

Parameters

NameTypeDescription
domainuint32Domain to get agents from (ZERO for Guards)

agentLeaf

Returns a leaf representing the current status of agent in the Agent Merkle Tree.

Will return an empty leaf, if agent is not added to the tree yet.

function agentLeaf(address agent) external view returns (bytes32 leaf);

Parameters

NameTypeDescription
agentaddressAgent address

Returns

NameTypeDescription
leafbytes32Agent leaf in the Agent Merkle Tree

leafsAmount

Returns a total amount of leafs representing known agents.

This includes active, unstaking, resting and slashed agents. This also includes an empty leaf as the very first entry.

function leafsAmount() external view returns (uint256 amount);

allLeafs

Returns a full list of leafs from the Agent Merkle Tree.

This might consume a lot of gas, do not use this on-chain.

function allLeafs() external view returns (bytes32[] memory leafs);

getLeafs

Returns a list of leafs from the Agent Merkle Tree with indexes [indexFrom .. indexFrom + amount).

This might consume a lot of gas, do not use this on-chain.

Will return less than amount entries, if indexFrom + amount > leafsAmount

function getLeafs(uint256 indexFrom, uint256 amount) external view returns (bytes32[] memory leafs);

getProof

Returns a proof of inclusion of the agent in the Agent Merkle Tree.

Will return a proof for an empty leaf, if agent is not added to the tree yet. This proof could be used by ANY next new agent that calls {addAgent}.

This WILL consume a lot of gas, do not use this on-chain.

The alternative way to create a proof is to fetch the full list of leafs using either {allLeafs} or {getLeafs}, and create a merkle proof from that.

function getProof(address agent) external view returns (bytes32[] memory proof);

Parameters

NameTypeDescription
agentaddressAgent address

Returns

NameTypeDescription
proofbytes32[]Merkle proof for the agent

InterfaceDestination

Git Source

Functions

passAgentRoot

Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.

Will do nothing, if root optimistic period is not over.

function passAgentRoot() external returns (bool rootPending);

Returns

NameTypeDescription
rootPendingboolWhether there is a pending agent merkle root left

acceptAttestation

Accepts an attestation, which local AgentManager verified to have been signed by an active Notary for this chain.

Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.

  • Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.
  • Messages coming from chains included in the Attestation's snapshot could be proven.
  • Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.

Will revert if any of these is true:

  • Called by anyone other than local AgentManager.
  • Attestation payload is not properly formatted.
  • Attestation signer is in Dispute.
  • Attestation's snapshot root has been previously submitted. Note: agentRoot and snapGas have been verified by the local AgentManager.
function acceptAttestation(
    uint32 notaryIndex,
    uint256 sigIndex,
    bytes memory attPayload,
    bytes32 agentRoot,
    ChainGas[] memory snapGas
) external returns (bool wasAccepted);

Parameters

NameTypeDescription
notaryIndexuint32Index of Attestation Notary in Agent Merkle Tree
sigIndexuint256Index of stored Notary signature
attPayloadbytesRaw payload with Attestation data
agentRootbytes32Agent Merkle Root from the Attestation
snapGasChainGas[]Gas data for each chain in the Attestation's snapshot

Returns

NameTypeDescription
wasAcceptedboolWhether the Attestation was accepted

attestationsAmount

Returns the total amount of Notaries attestations that have been accepted.

function attestationsAmount() external view returns (uint256);

getAttestation

Returns a Notary-signed attestation with a given index.

Index refers to the list of all attestations accepted by this contract.

Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit. Will return an empty signature if this contract is deployed on Synapse Chain.

function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);

Parameters

NameTypeDescription
indexuint256Attestation index

Returns

NameTypeDescription
attPayloadbytesRaw payload with Attestation data
attSignaturebytesNotary signature for the reported attestation

getGasData

Returns the gas data for a given chain from the latest accepted attestation with that chain.

Will return empty values if there is no data for the domain, or if the notary who provided the data is in dispute.

function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);

Parameters

NameTypeDescription
domainuint32Domain for the chain

Returns

NameTypeDescription
gasDataGasDataGas data for the chain
dataMaturityuint256Gas data age in seconds

destStatus

Returns status of Destination contract as far as snapshot/agent roots are concerned

function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);

Returns

NameTypeDescription
snapRootTimeuint40Timestamp when latest snapshot root was accepted
agentRootTimeuint40Timestamp when latest agent root was accepted
notaryIndexuint32Index of Notary who signed the latest agent root

nextAgentRoot

Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.

function nextAgentRoot() external view returns (bytes32);

lastAttestationNonce

Returns the nonce of the last attestation submitted by a Notary with a given agent index.

Will return zero if the Notary hasn't submitted any attestations yet.

function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);

InterfaceGasOracle

Git Source

Functions

updateGasData

Fetches the latest gas data for the chain from Destination contract, and uses it to update the oracle values for the requested chain.

function updateGasData(uint32 domain) external;

Parameters

NameTypeDescription
domainuint32Domain to update the gas data for

getGasData

Returns the gas data for the local chain.

function getGasData() external view returns (uint256 paddedGasData);

getDecodedGasData

Returns the gas data for the given domain, in the decoded format.

function getDecodedGasData(uint32 domain)
    external
    view
    returns (
        uint256 gasPrice,
        uint256 dataPrice,
        uint256 execBuffer,
        uint256 amortAttCost,
        uint256 etherPrice,
        uint256 markup
    );

Parameters

NameTypeDescription
domainuint32Domain of chain to get gas data for

Returns

NameTypeDescription
gasPriceuint256Gas price for the chain (in Wei per gas unit)
dataPriceuint256Calldata price (in Wei per byte of content)
execBufferuint256Tx fee safety buffer for message execution (in Wei)
amortAttCostuint256Amortized cost for attestation submission (in Wei)
etherPriceuint256Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)
markupuint256Markup for the message execution (in BWAD)

getMinimumTips

Returns the minimum tips for sending a message to a given destination.

function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)
    external
    view
    returns (uint256 paddedTips);

Parameters

NameTypeDescription
destinationuint32Domain of destination chain
paddedRequestuint256Padded encoded message execution request on destination chain
contentLengthuint256The length of the message content

Returns

NameTypeDescription
paddedTipsuint256Padded encoded minimum tips information

InterfaceInbox

Git Source

Functions

submitSnapshot

Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.

Snapshot is a list of states for a set of Origin contracts residing on any of the chains.

  • Guard-signed snapshots: all the states in the snapshot become available for Notary signing.
  • Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e. snapshots which are only using states previously submitted by any of the Guards.
  • Notary doesn't have to use states submitted by a single Guard in their snapshot.
  • Notary could then proceed to sign the attestation for their submitted snapshot.

Will revert if any of these is true:

  • Snapshot payload is not properly formatted.
  • Snapshot signer is not an active Agent.
  • Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.
  • Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.
  • Note: Agent will NOT be slashed for submitting such a snapshot.

Notary will need to provide both agentRoot and snapGas when submitting an attestation on the remote chain (the attestation contains only their merged hash). These are returned by this function, and could be also obtained by calling getAttestation(nonce) or getLatestNotaryAttestation(notary).

function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)
    external
    returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);

Parameters

NameTypeDescription
snapPayloadbytesRaw payload with snapshot data
snapSignaturebytesAgent signature for the snapshot

Returns

NameTypeDescription
attPayloadbytesRaw payload with data for attestation derived from Notary snapshot. Empty payload, if a Guard snapshot was submitted.
agentRootbytes32Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)
snapGasuint256[]Gas data for each chain in the snapshot Empty list, if a Guard snapshot was submitted.

submitReceipt

Accepts a receipt signed by a Notary and passes it to Summit contract to save.

Receipt is a statement about message execution status on the remote chain.

  • This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.

Will revert if any of these is true:

  • Receipt payload is not properly formatted.
  • Receipt signer is not an active Notary.
  • Receipt signer is in Dispute.
  • Receipt's snapshot root is unknown.
  • Provided tips could not be proven against the message hash.
function submitReceipt(
    bytes memory rcptPayload,
    bytes memory rcptSignature,
    uint256 paddedTips,
    bytes32 headerHash,
    bytes32 bodyHash
) external returns (bool wasAccepted);

Parameters

NameTypeDescription
rcptPayloadbytesRaw payload with receipt data
rcptSignaturebytesNotary signature for the receipt
paddedTipsuint256Tips for the message execution
headerHashbytes32Hash of the message header
bodyHashbytes32Hash of the message body excluding the tips

Returns

NameTypeDescription
wasAcceptedboolWhether the receipt was accepted

submitReceiptReport

Accepts a Guard's receipt report signature, as well as Notary signature for the reported Receipt.

ReceiptReport is a Guard statement saying "Reported receipt is invalid".

  • This results in an opened Dispute between the Guard and the Notary.
  • Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from verifyReceipt() successful call that led to Notary being slashed in Summit on Synapse Chain.

Will revert if any of these is true:

  • Receipt payload is not properly formatted.
  • Receipt Report signer is not an active Guard.
  • Receipt signer is not an active Notary.
function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)
    external
    returns (bool wasAccepted);

Parameters

NameTypeDescription
rcptPayloadbytesRaw payload with Receipt data that Guard reports as invalid
rcptSignaturebytesNotary signature for the reported receipt
rrSignaturebytesGuard signature for the report

Returns

NameTypeDescription
wasAcceptedboolWhether the Report was accepted (resulting in Dispute between the agents)

passReceipt

Passes the message execution receipt from Destination to the Summit contract to save.

Will revert if any of these is true:

  • Called by anyone other than Destination.

If a receipt is not accepted, any of the Notaries can submit it later using submitReceipt.

function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)
    external
    returns (bool wasAccepted);

Parameters

NameTypeDescription
attNotaryIndexuint32Index of the Notary who signed the attestation
attNonceuint32Nonce of the attestation used for proving the executed message
paddedTipsuint256Tips for the message execution
rcptPayloadbytesRaw payload with message execution receipt

Returns

NameTypeDescription
wasAcceptedboolWhether the receipt was accepted

verifyAttestation

Verifies an attestation signed by a Notary.

  • Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).
  • Slashes the Notary, if the attestation is invalid.

Will revert if any of these is true:

  • Attestation payload is not properly formatted.
  • Attestation signer is not an active Notary.
function verifyAttestation(bytes memory attPayload, bytes memory attSignature)
    external
    returns (bool isValidAttestation);

Parameters

NameTypeDescription
attPayloadbytesRaw payload with Attestation data
attSignaturebytesNotary signature for the attestation

Returns

NameTypeDescription
isValidAttestationboolWhether the provided attestation is valid. Notary is slashed, if return value is FALSE.

verifyAttestationReport

Verifies a Guard's attestation report signature.

  • Does nothing, if the report is valid (if the reported attestation is invalid).
  • Slashes the Guard, if the report is invalid (if the reported attestation is valid).

Will revert if any of these is true:

  • Attestation payload is not properly formatted.
  • Attestation Report signer is not an active Guard.
function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)
    external
    returns (bool isValidReport);

Parameters

NameTypeDescription
attPayloadbytesRaw payload with Attestation data that Guard reports as invalid
arSignaturebytesGuard signature for the report

Returns

NameTypeDescription
isValidReportboolWhether the provided report is valid. Guard is slashed, if return value is FALSE.

InterfaceLightInbox

Git Source

Functions

submitAttestation

Accepts an attestation signed by a Notary and passes it to Destination contract to save.

Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.

  • Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.
  • Messages coming from chains included in the Attestation's snapshot could be proven.
  • Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.

Will revert if any of these is true:

  • Attestation payload is not properly formatted.
  • Attestation signer is not an active Notary for local domain.
  • Attestation signer is in Dispute.
  • Attestation's snapshot root has been previously submitted.
  • Attestation's data hash doesn't match the hash of provided agentRoot and snapshot gas data.
function submitAttestation(
    bytes memory attPayload,
    bytes memory attSignature,
    bytes32 agentRoot,
    uint256[] memory snapGas
) external returns (bool wasAccepted);

Parameters

NameTypeDescription
attPayloadbytesRaw payload with Attestation data
attSignaturebytesNotary signature for the attestation
agentRootbytes32Agent Merkle Root from the Attestation
snapGasuint256[]Gas data for each chain in the snapshot

Returns

NameTypeDescription
wasAcceptedboolWhether the Attestation was accepted

submitAttestationReport

Accepts a Guard's attestation report signature, as well as Notary signature for the reported Attestation.

AttestationReport is a Guard statement saying "Reported attestation is invalid".

  • This results in an opened Dispute between the Guard and the Notary.
  • Note: Guard could (but doesn't have to) form a AttestationReport and use attestation signature from verifyAttestation() successful call that led to Notary being slashed in Summit on Synapse Chain.

Will revert if any of these is true:

  • Attestation payload is not properly formatted.
  • Attestation Report signer is not an active Guard.
  • Attestation signer is not an active Notary for local domain.
function submitAttestationReport(bytes memory attPayload, bytes memory arSignature, bytes memory attSignature)
    external
    returns (bool wasAccepted);

Parameters

NameTypeDescription
attPayloadbytesRaw payload with Attestation data that Guard reports as invalid
arSignaturebytesGuard signature for the report
attSignaturebytesNotary signature for the reported attestation

Returns

NameTypeDescription
wasAcceptedboolWhether the Report was accepted (resulting in Dispute between the agents)

InterfaceLightManager

Git Source

Functions

updateAgentStatus

Updates agent status, using a proof against the latest known Agent Merkle Root.

Will revert if the provided proof doesn't match the latest merkle root.

function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;

Parameters

NameTypeDescription
agentaddressAgent address
statusAgentStatusStructure specifying agent status: (flag, domain, index)
proofbytes32[]Merkle proof of Active status for the agent

setAgentRoot

Updates the root of Agent Merkle Tree that the Light Manager is tracking. Could be only called by a local Destination contract, which is supposed to verify the attested Agent Merkle Roots.

function setAgentRoot(bytes32 agentRoot_) external;

Parameters

NameTypeDescription
agentRoot_bytes32New Agent Merkle Root

proposeAgentRootWhenStuck

Allows contract owner to set the agent root to resolve the "stuck" chain by proposing the new agent root. The contract owner will be able to resolve the proposed agent root after a certain period of time. Note: this function could be called multiple times, each time the timer will be reset. This could only be called if no fresh data has been submitted by the Notaries to the Inbox, indicating that the chain is stuck for one of the reasons:

  • All active Notaries are in Dispute.
  • No active Notaries exist under the current agent root.

*Will revert if any of the following conditions is met:

  • Caller is not the contract owner.
  • Agent root is empty.
  • The chain is not in a stuck state (has recently received a fresh data from the Notaries).*
function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;

Parameters

NameTypeDescription
agentRoot_bytes32New Agent Merkle Root that is proposed to be set

cancelProposedAgentRoot

Allows contract owner to cancel the previously proposed agent root.

*Will revert if any of the following conditions is met:

  • Caller is not the contract owner.
  • No agent root was proposed.*
function cancelProposedAgentRoot() external;

resolveProposedAgentRoot

Allows contract owner to resolve the previously proposed agent root. This will update the agent root, allowing the agents to update their status, effectively resolving the "stuck" chain.

*Will revert if any of the following conditions is met:

  • Caller is not the contract owner.
  • No agent root was proposed.
  • Not enough time has passed since the agent root was proposed.*
function resolveProposedAgentRoot() external;

remoteWithdrawTips

Withdraws locked base message tips from local Origin to the recipient.

Could only be remote-called by BondingManager contract on Synapse Chain. Note: as an extra security check this function returns its own selector, so that Destination could verify that a "remote" function was called when executing a manager message.

function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)
    external
    returns (bytes4 magicValue);

Parameters

NameTypeDescription
msgOriginuint32
proofMaturityuint256
recipientaddressAddress to withdraw tips to
amountuint256Tips value to withdraw

proposedAgentRootData

Returns the latest proposed agent root and the timestamp when it was proposed.

Will return zero values if no agent root was proposed, or if the proposed agent root was already resolved.

function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);

InterfaceOrigin

Git Source

Functions

sendBaseMessage

Send a message to the recipient located on destination domain.

*Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered. Will revert if any of these is true:

  • destination is equal to contract's local domain
  • content length is greater than MAX_CONTENT_BYTES
  • msg.value is lower than value of minimum tips for the given message*
function sendBaseMessage(
    uint32 destination,
    bytes32 recipient,
    uint32 optimisticPeriod,
    uint256 paddedRequest,
    bytes memory content
) external payable returns (uint32 messageNonce, bytes32 messageHash);

Parameters

NameTypeDescription
destinationuint32Domain of destination chain
recipientbytes32Address of recipient on destination chain as bytes32
optimisticPerioduint32Optimistic period for message execution on destination chain
paddedRequestuint256Padded encoded message execution request on destination chain
contentbytesRaw bytes content of message

Returns

NameTypeDescription
messageNonceuint32Nonce of the sent message
messageHashbytes32Hash of the sent message

sendManagerMessage

Send a manager message to the destination domain.

This could only be called by AgentManager, which takes care of encoding the calldata payload. Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain so that the AgentManager could verify where the Manager Message came from and how mature is the proof. Note: function is not payable, as no tips are required for sending a manager message. Will revert if destination is equal to contract's local domain.

function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)
    external
    returns (uint32 messageNonce, bytes32 messageHash);

Parameters

NameTypeDescription
destinationuint32Domain of destination chain
optimisticPerioduint32Optimistic period for message execution on destination chain
payloadbytesPayload for calling AgentManager on destination chain (with extra security args)

withdrawTips

Withdraws locked base message tips to the recipient.

Could only be called by a local AgentManager.

function withdrawTips(address recipient, uint256 amount) external;

Parameters

NameTypeDescription
recipientaddressAddress to withdraw tips to
amountuint256Tips value to withdraw

getMinimumTipsValue

Returns the minimum tips value for sending a message to a given destination.

Using at least tipsValue as msg.value for sendBaseMessage() will guarantee that the message will be accepted.

function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)
    external
    view
    returns (uint256 tipsValue);

Parameters

NameTypeDescription
destinationuint32Domain of destination chain
paddedRequestuint256Padded encoded message execution request on destination chain
contentLengthuint256The length of the message content

Returns

NameTypeDescription
tipsValueuint256Minimum tips value for a message to be accepted

InterfaceSummit

Git Source

Functions

acceptReceipt

Accepts a receipt, which local AgentManager verified to have been signed by an active Notary.

Receipt is a statement about message execution status on the remote chain.

  • This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.
  • Notary who signed the receipt is referenced as the "Receipt Notary".
  • Notary who signed the attestation on destination chain is referenced as the "Attestation Notary".

Will revert if any of these is true:

  • Called by anyone other than local AgentManager.
  • Receipt body payload is not properly formatted.
  • Receipt signer is in Dispute.
  • Receipt's snapshot root is unknown.
function acceptReceipt(
    uint32 rcptNotaryIndex,
    uint32 attNotaryIndex,
    uint256 sigIndex,
    uint32 attNonce,
    uint256 paddedTips,
    bytes memory rcptPayload
) external returns (bool wasAccepted);

Parameters

NameTypeDescription
rcptNotaryIndexuint32Index of Receipt Notary in Agent Merkle Tree
attNotaryIndexuint32Index of Attestation Notary in Agent Merkle Tree
sigIndexuint256Index of stored Notary signature
attNonceuint32Nonce of the attestation used for proving the executed message
paddedTipsuint256Padded encoded paid tips information
rcptPayloadbytesRaw payload with message execution receipt

Returns

NameTypeDescription
wasAcceptedboolWhether the receipt was accepted

acceptGuardSnapshot

Accepts a snapshot, which local AgentManager verified to have been signed by an active Guard.

Snapshot is a list of states for a set of Origin contracts residing on any of the chains. All the states in the Guard-signed snapshot become available for Notary signing. Will revert if any of these is true:

  • Called by anyone other than local AgentManager.
  • Snapshot payload is not properly formatted.
  • Snapshot contains a state older then the Guard has previously submitted.
function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;

Parameters

NameTypeDescription
guardIndexuint32Index of Guard in Agent Merkle Tree
sigIndexuint256Index of stored Agent signature
snapPayloadbytesRaw payload with snapshot data

acceptNotarySnapshot

Accepts a snapshot, which local AgentManager verified to have been signed by an active Notary.

Snapshot is a list of states for a set of Origin contracts residing on any of the chains. Snapshot Merkle Root is calculated and saved for valid snapshots, i.e. snapshots which are only using states previously submitted by any of the Guards.

  • Notary could use states singed by the same of different Guards in their snapshot.
  • Notary could then proceed to sign the attestation for their submitted snapshot.

Will revert if any of these is true:

  • Called by anyone other than local AgentManager.
  • Snapshot payload is not properly formatted.
  • Snapshot contains a state older then the Notary has previously submitted.
  • Snapshot contains a state that no Guard has previously submitted.
function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)
    external
    returns (bytes memory attPayload);

Parameters

NameTypeDescription
notaryIndexuint32Index of Notary in Agent Merkle Tree
sigIndexuint256Index of stored Agent signature
agentRootbytes32Current root of the Agent Merkle Tree
snapPayloadbytesRaw payload with snapshot data

Returns

NameTypeDescription
attPayloadbytesRaw payload with data for attestation derived from Notary snapshot.

distributeTips

Distributes tips using the first Receipt from the "receipt quarantine queue". Possible scenarios:

  • Receipt queue is empty => does nothing
  • Receipt optimistic period is not over => does nothing
  • Either of Notaries present in Receipt was slashed => receipt is deleted from the queue
  • Either of Notaries present in Receipt in Dispute => receipt is moved to the end of queue
  • None of the above => receipt tips are distributed

Returned value makes it possible to do the following: while (distributeTips()) {}

function distributeTips() external returns (bool queuePopped);

Returns

NameTypeDescription
queuePoppedboolWhether the first element was popped from the queue

withdrawTips

Withdraws locked base message tips from requested domain Origin to the recipient. This is done by a call to a local Origin contract, or by a manager message to the remote chain.

This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.

function withdrawTips(uint32 origin, uint256 amount) external;

Parameters

NameTypeDescription
originuint32Domain of chain to withdraw tips on
amountuint256Amount of tips to withdraw

actorTips

Returns earned and claimed tips for the actor. Note: Tips for address(0) belong to the Treasury.

function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);

Parameters

NameTypeDescription
actoraddressAddress of the actor
originuint32Domain where the tips were initially paid

Returns

NameTypeDescription
earneduint128Total amount of origin tips the actor has earned so far
claimeduint128Total amount of origin tips the actor has claimed so far

receiptQueueLength

Returns the amount of receipts in the "Receipt Quarantine Queue".

function receiptQueueLength() external view returns (uint256);

getLatestState

Returns the state with the highest known nonce submitted by any of the currently active Guards.

function getLatestState(uint32 origin) external view returns (bytes memory statePayload);

Parameters

NameTypeDescription
originuint32Domain of origin chain

Returns

NameTypeDescription
statePayloadbytesRaw payload with latest active Guard state for origin

Contents

Contents

Attestation

Git Source

Attestation is a memory view over a formatted attestation payload.

type Attestation is uint256;

AttestationLib

Git Source

Attestation

Attestation structure represents the "Snapshot Merkle Tree" created from every Notary snapshot accepted by the Summit contract. Attestation includes" the root of the "Snapshot Merkle Tree", as well as additional metadata.

Steps for creation of "Snapshot Merkle Tree":

  1. The list of hashes is composed for states in the Notary snapshot.
  2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.
  3. Values from the list are used as leafs and the merkle tree is constructed.

Differences between a State and Attestation

Similar to Origin, every derived Notary's "Snapshot Merkle Root" is saved in Summit contract. The main difference is that Origin contract itself is keeping track of an incremental merkle tree, by inserting the hash of the sent message and calculating the new "Origin Merkle Root". While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the "Snapshot Merkle Root".

  • Origin's State is "state of Origin Merkle Tree after N-th message was sent".
  • Summit's Attestation is "data for the N-th accepted Notary Snapshot" + "agent merkle root at the time snapshot was submitted" + "attestation metadata".

Attestation validity

  • Attestation is considered "valid" in Summit contract, if it matches the N-th (nonce) snapshot submitted by Notaries, as well as the historical agent merkle root.
  • Attestation is considered "valid" in Origin contract, if its underlying Snapshot is "valid".
  • This means that a snapshot could be "valid" in Summit contract and "invalid" in Origin, if the underlying snapshot is invalid (i.e. one of the states in the list is invalid).
  • The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).
  • Attestation is considered "globally valid", if it is valid in the Summit and all the Origin contracts.

Memory layout of Attestation fields

PositionFieldTypeBytesDescription
[000..032)snapRootbytes3232Root for "Snapshot Merkle Tree" created from a Notary snapshot
[032..064)dataHashbytes3232Agent Root and SnapGasHash combined into a single hash
[064..068)nonceuint324Total amount of all accepted Notary snapshots
[068..073)blockNumberuint405Block when this Notary snapshot was accepted in Summit
[073..078)timestampuint405Time when this Notary snapshot was accepted in Summit

Attestation could be signed by a Notary and submitted to Destination in order to use if for proving messages coming from origin chains that the initial snapshot refers to.

State Variables

OFFSET_SNAP_ROOT

The variables below are not supposed to be used outside of the library directly.

uint256 private constant OFFSET_SNAP_ROOT = 0;

OFFSET_DATA_HASH

uint256 private constant OFFSET_DATA_HASH = 32;

OFFSET_NONCE

uint256 private constant OFFSET_NONCE = 64;

OFFSET_BLOCK_NUMBER

uint256 private constant OFFSET_BLOCK_NUMBER = 68;

OFFSET_TIMESTAMP

uint256 private constant OFFSET_TIMESTAMP = 73;

Functions

formatAttestation

Returns a formatted Attestation payload with provided fields.

function formatAttestation(bytes32 snapRoot_, bytes32 dataHash_, uint32 nonce_, uint40 blockNumber_, uint40 timestamp_)
    internal
    pure
    returns (bytes memory);

Parameters

NameTypeDescription
snapRoot_bytes32Snapshot merkle tree's root
dataHash_bytes32Agent Root and SnapGasHash combined into a single hash
nonce_uint32Attestation Nonce
blockNumber_uint40Block number when attestation was created in Summit
timestamp_uint40Block timestamp when attestation was created in Summit

Returns

NameTypeDescription
<none>bytesFormatted attestation

castToAttestation

Returns an Attestation view over the given payload.

Will revert if the payload is not an attestation.

function castToAttestation(bytes memory payload) internal pure returns (Attestation);

castToAttestation

Casts a memory view to an Attestation view.

Will revert if the memory view is not over an attestation.

function castToAttestation(MemView memView) internal pure returns (Attestation);

isAttestation

Checks that a payload is a formatted Attestation.

function isAttestation(MemView memView) internal pure returns (bool);

hashValid

Returns the hash of an Attestation, that could be later signed by a Notary to signal that the attestation is valid.

function hashValid(Attestation att) internal pure returns (bytes32);

hashInvalid

Returns the hash of an Attestation, that could be later signed by a Guard to signal that the attestation is invalid.

function hashInvalid(Attestation att) internal pure returns (bytes32);

unwrap

Convenience shortcut for unwrapping a view.

function unwrap(Attestation att) internal pure returns (MemView);

snapRoot

Returns root of the Snapshot merkle tree created in the Summit contract.

function snapRoot(Attestation att) internal pure returns (bytes32);

dataHash

Returns hash of the Agent Root and SnapGasHash combined into a single hash.

function dataHash(Attestation att) internal pure returns (bytes32);

dataHash

Returns hash of the Agent Root and SnapGasHash combined into a single hash.

function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32);

nonce

Returns nonce of Summit contract at the time, when attestation was created.

function nonce(Attestation att) internal pure returns (uint32);

blockNumber

Returns a block number when attestation was created in Summit.

function blockNumber(Attestation att) internal pure returns (uint40);

timestamp

Returns a block timestamp when attestation was created in Summit.

This is the timestamp according to the Synapse Chain.

function timestamp(Attestation att) internal pure returns (uint40);

BaseMessage

Git Source

BaseMessage is a memory view over the base message supported by Origin-Destination

type BaseMessage is uint256;

BaseMessageLib

Git Source

BaseMessage structure represents a base message sent via the Origin-Destination contracts.

  • It only contains data relevant to the base message, the rest of data is encoded in the message header.
  • sender and recipient for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.
  • tips and request parameters are specified by a message sender

Origin will calculate minimum tips for given request and content length, and will reject messages with tips lower than that.

Memory layout of BaseMessage fields

PositionFieldTypeBytesDescription
[000..032)tipsuint25632Encoded tips paid on origin chain
[032..064)senderbytes3232Sender address on origin chain
[064..096)recipientbytes3232Recipient address on destination chain
[096..116)requestuint16020Encoded request for message execution
[104..AAA)contentbytes??Content to be passed to recipient

State Variables

OFFSET_TIPS

The variables below are not supposed to be used outside of the library directly.

uint256 private constant OFFSET_TIPS = 0;

OFFSET_SENDER

uint256 private constant OFFSET_SENDER = 32;

OFFSET_RECIPIENT

uint256 private constant OFFSET_RECIPIENT = 64;

OFFSET_REQUEST

uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;

OFFSET_CONTENT

uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;

Functions

formatBaseMessage

Returns a formatted BaseMessage payload with provided fields.

function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)
    internal
    pure
    returns (bytes memory);

Parameters

NameTypeDescription
tips_TipsEncoded tips information
sender_bytes32Sender address on origin chain
recipient_bytes32Recipient address on destination chain
request_RequestEncoded request for message execution
content_bytesRaw content to be passed to recipient on destination chain

Returns

NameTypeDescription
<none>bytesFormatted base message

castToBaseMessage

Returns a BaseMessage view over the given payload.

Will revert if the payload is not a base message.

function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage);

castToBaseMessage

Casts a memory view to a BaseMessage view.

Will revert if the memory view is not over a base message payload.

function castToBaseMessage(MemView memView) internal pure returns (BaseMessage);

isBaseMessage

Checks that a payload is a formatted BaseMessage.

function isBaseMessage(MemView memView) internal pure returns (bool);

unwrap

Convenience shortcut for unwrapping a view.

function unwrap(BaseMessage baseMessage) internal pure returns (MemView);

leaf

Returns baseMessage's hash: a leaf to be inserted in the "Message mini-Merkle tree".

function leaf(BaseMessage baseMessage) internal pure returns (bytes32);

bodyLeaf

Returns hash for the "everything but tips" part of the base message.

function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32);

tips

Returns encoded tips paid on origin chain.

function tips(BaseMessage baseMessage) internal pure returns (Tips);

sender

Returns sender address on origin chain.

function sender(BaseMessage baseMessage) internal pure returns (bytes32);

recipient

Returns recipient address on destination chain.

function recipient(BaseMessage baseMessage) internal pure returns (bytes32);

request

Returns an encoded request for message execution on destination chain.

function request(BaseMessage baseMessage) internal pure returns (Request);

content

Returns an untyped memory view over the content to be passed to recipient.

function content(BaseMessage baseMessage) internal pure returns (MemView);

CallData

Git Source

*CallData is a memory view over the payload to be used for an external call, i.e. recipient.call(callData). Its length is always (4 + 32 * N) bytes:

  • First 4 bytes represent the function selector.
  • 32 * N bytes represent N words that function arguments occupy.*
type CallData is uint256;

Signature

Git Source

Attach library functions to CallData

Signature is a memory view over a "65 bytes" array representing a ECDSA signature.

type Signature is uint256;

ByteString

Git Source

Attach library functions to Signature

State Variables

SIGNATURE_LENGTH

non-compact ECDSA signatures are enforced as of OZ 4.7.3 Signature payload memory layout [000 .. 032) r bytes32 32 bytes [032 .. 064) s bytes32 32 bytes [064 .. 065) v uint8 1 byte

uint256 internal constant SIGNATURE_LENGTH = 65;

OFFSET_R

uint256 private constant OFFSET_R = 0;

OFFSET_S

uint256 private constant OFFSET_S = 32;

OFFSET_V

uint256 private constant OFFSET_V = 64;

SELECTOR_LENGTH

Calldata memory layout [000 .. 004) selector bytes4 4 bytes Optional: N function arguments [004 .. 036) arg1 bytes32 32 bytes .. [AAA .. END) argN bytes32 32 bytes

uint256 internal constant SELECTOR_LENGTH = 4;

OFFSET_SELECTOR

uint256 private constant OFFSET_SELECTOR = 0;

OFFSET_ARGUMENTS

uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;

Functions

formatSignature

Constructs the signature payload from the given values.

Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure that params are given in the right order.

function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory);

castToSignature

Returns a Signature view over for the given payload.

Will revert if the payload is not a signature.

function castToSignature(bytes memory payload) internal pure returns (Signature);

castToSignature

Casts a memory view to a Signature view.

Will revert if the memory view is not over a signature.

function castToSignature(MemView memView) internal pure returns (Signature);

isSignature

Checks that a byte string is a signature

function isSignature(MemView memView) internal pure returns (bool);

unwrap

Convenience shortcut for unwrapping a view.

function unwrap(Signature signature) internal pure returns (MemView);

toRSV

Unpacks signature payload into (r, s, v) parameters.

Make sure to verify signature length with isSignature() beforehand.

function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v);

addPrefix

Constructs the calldata with the modified arguments: the existing arguments are prepended with the arguments from the prefix.

*Given:

  • calldata = abi.encodeWithSelector(foo.selector, d, e);
  • prefix = abi.encode(a, b, c);
  • a, b, c are arguments of static type (i.e. not dynamically sized ones) Then:
  • Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)
  • Returned calldata will trigger foo(a, b, c, d, e) when used for a contract call. Note: for clarification as to what types are considered static, see https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding*
function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory);

Parameters

NameTypeDescription
callDataCallDataCalldata that needs to be modified
prefixbytesABI-encoded arguments to use as the first arguments in the new calldata

Returns

NameTypeDescription
<none>bytesModified calldata having prefix as the first arguments.

castToCallData

Returns a CallData view over for the given payload.

Will revert if the memory view is not over a calldata.

function castToCallData(bytes memory payload) internal pure returns (CallData);

castToCallData

Casts a memory view to a CallData view.

Will revert if the memory view is not over a calldata.

function castToCallData(MemView memView) internal pure returns (CallData);

isCallData

Checks that a byte string is a valid calldata, i.e. a function selector, followed by arbitrary amount of arguments.

function isCallData(MemView memView) internal pure returns (bool);

unwrap

Convenience shortcut for unwrapping a view.

function unwrap(CallData callData) internal pure returns (MemView);

leaf

Returns callData's hash: a leaf to be inserted in the "Message mini-Merkle tree".

function leaf(CallData callData) internal pure returns (bytes32);

argumentWords

Returns amount of memory words (32 byte chunks) the function arguments occupy in the calldata.

This might differ from amount of arguments supplied, if any of the arguments occupies more than one memory slot. It is true, however, that argument part of the payload occupies exactly N words, even for dynamic types like bytes

function argumentWords(CallData callData) internal pure returns (uint256);

callSelector

Returns selector for the provided calldata.

function callSelector(CallData callData) internal pure returns (bytes4);

arguments

Returns abi encoded arguments for the provided calldata.

function arguments(CallData callData) internal pure returns (MemView);

_fullWords

Checks if length is full amount of memory words (32 bytes).

function _fullWords(uint256 length) internal pure returns (bool);

MemView

Git Source

MemView is an untyped view over a portion of memory to be used instead of bytes memory

type MemView is uint256;

MemViewLib

Git Source

Library for operations with the memory views. Forked from https://github.com/summa-tx/memview-sol with several breaking changes:

  • The codebase is ported to Solidity 0.8
  • Custom errors are added
  • The runtime type checking is replaced with compile-time check provided by User-Defined Value Types https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types
  • uint256 is used as the underlying type for the "memory view" instead of bytes29. It is wrapped into MemView custom type in order not to be confused with actual integers.
  • Therefore the "type" field is discarded, allowing to allocate 16 bytes for both view location and length
  • The documentation is expanded
  • Library functions unused by the rest of the codebase are removed

Attach library functions to MemView

Functions

build

Stack layout for uint256 (from highest bits to lowest) (32 .. 16] loc 16 bytes Memory address of underlying bytes (16 .. 00] len 16 bytes Length of underlying bytes

Instantiate a new untyped memory view. This should generally not be called directly. Prefer ref wherever possible.

function build(uint256 loc_, uint256 len_) internal pure returns (MemView);

Parameters

NameTypeDescription
loc_uint256The memory address
len_uint256The length

Returns

NameTypeDescription
<none>MemViewThe new view with the specified location and length

ref

Instantiate a memory view from a byte array.

Note that due to Solidity memory representation, it is not possible to implement a deref, as the bytes type stores its len in memory.

function ref(bytes memory arr) internal pure returns (MemView);

Parameters

NameTypeDescription
arrbytesThe byte array

Returns

NameTypeDescription
<none>MemViewThe memory view over the provided byte array

clone

Copies the referenced memory to a new loc in memory, returning a bytes pointing to the new memory.

function clone(MemView memView) internal view returns (bytes memory arr);

Parameters

NameTypeDescription
memViewMemViewThe memory view

Returns

NameTypeDescription
arrbytesThe cloned byte array

join

Copies all views, joins them into a new bytearray.

function join(MemView[] memory memViews) internal view returns (bytes memory arr);

Parameters

NameTypeDescription
memViewsMemView[]The memory views

Returns

NameTypeDescription
arrbytesThe new byte array with joined data behind the given views

loc

Returns the memory address of the underlying bytes.

function loc(MemView memView) internal pure returns (uint256 loc_);

Parameters

NameTypeDescription
memViewMemViewThe memory view

Returns

NameTypeDescription
loc_uint256The memory address

len

Returns the number of bytes of the view.

function len(MemView memView) internal pure returns (uint256 len_);

Parameters

NameTypeDescription
memViewMemViewThe memory view

Returns

NameTypeDescription
len_uint256The length of the view

end

Returns the endpoint of memView.

function end(MemView memView) internal pure returns (uint256 end_);

Parameters

NameTypeDescription
memViewMemViewThe memory view

Returns

NameTypeDescription
end_uint256The endpoint of memView

words

Returns the number of memory words this memory view occupies, rounded up.

function words(MemView memView) internal pure returns (uint256 words_);

Parameters

NameTypeDescription
memViewMemViewThe memory view

Returns

NameTypeDescription
words_uint256The number of memory words

footprint

Returns the in-memory footprint of a fresh copy of the view.

function footprint(MemView memView) internal pure returns (uint256 footprint_);

Parameters

NameTypeDescription
memViewMemViewThe memory view

Returns

NameTypeDescription
footprint_uint256The in-memory footprint of a fresh copy of the view.

keccak

Returns the keccak256 hash of the underlying memory

function keccak(MemView memView) internal pure returns (bytes32 digest);

Parameters

NameTypeDescription
memViewMemViewThe memory view

Returns

NameTypeDescription
digestbytes32The keccak256 hash of the underlying memory

keccakSalted

Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the resulting data.

function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted);

Parameters

NameTypeDescription
memViewMemViewThe memory view
saltbytes32

Returns

NameTypeDescription
digestSaltedbytes32keccak256(salt, keccak256(memView))

slice

Safe slicing without memory modification.

function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView);

Parameters

NameTypeDescription
memViewMemViewThe memory view
index_uint256The start index
len_uint256The length

Returns

NameTypeDescription
<none>MemViewThe new view for the slice of the given length starting from the given index

sliceFrom

Shortcut to slice. Gets a view representing bytes from index to end(memView).

function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView);

Parameters

NameTypeDescription
memViewMemViewThe memory view
index_uint256The start index

Returns

NameTypeDescription
<none>MemViewThe new view for the slice starting from the given index until the initial view endpoint

prefix

Shortcut to slice. Gets a view representing the first len bytes.

function prefix(MemView memView, uint256 len_) internal pure returns (MemView);

Parameters

NameTypeDescription
memViewMemViewThe memory view
len_uint256The length

Returns

NameTypeDescription
<none>MemViewThe new view for the slice of the given length starting from the initial view beginning

postfix

Shortcut to slice. Gets a view representing the last len byte.

function postfix(MemView memView, uint256 len_) internal pure returns (MemView);

Parameters

NameTypeDescription
memViewMemViewThe memory view
len_uint256The length

Returns

NameTypeDescription
<none>MemViewThe new view for the slice of the given length until the initial view endpoint

index

Load up to 32 bytes from the view onto the stack.

Returns a bytes32 with only the bytes_ HIGHEST bytes set. This can be immediately cast to a smaller fixed-length byte array. To automatically cast to an integer, use indexUint.

function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result);

Parameters

NameTypeDescription
memViewMemViewThe memory view
index_uint256The index
bytes_uint256The amount of bytes to load onto the stack

Returns

NameTypeDescription
resultbytes32The 32 byte result having only bytes_ highest bytes set

indexUint

Parse an unsigned integer from the view at index.

Requires that the view have >= bytes_ bytes following that index.

function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256);

Parameters

NameTypeDescription
memViewMemViewThe memory view
index_uint256The index
bytes_uint256The amount of bytes to load onto the stack

Returns

NameTypeDescription
<none>uint256The unsigned integer

indexAddress

Parse an address from the view at index.

Requires that the view have >= 20 bytes following that index.

function indexAddress(MemView memView, uint256 index_) internal pure returns (address);

Parameters

NameTypeDescription
memViewMemViewThe memory view
index_uint256The index

Returns

NameTypeDescription
<none>addressThe address

_unsafeBuildUnchecked

Returns a memory view over the specified memory location without checking if it points to unallocated memory.

function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView);

_unsafeCopyTo

Copy the view to a location, return an unsafe memory reference

Super Dangerous direct memory access. This reference can be overwritten if anything else modifies memory (!!!). As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data is not overwritten. This function is private to prevent unsafe usage by callers.

function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView);

Parameters

NameTypeDescription
memViewMemViewThe memory view
newLocuint256The new location to copy the underlying view data

Returns

NameTypeDescription
<none>MemViewThe memory view over the unsafe memory with the copied underlying data

_unsafeJoin

Join the views in memory, return an unsafe reference to the memory.

Super Dangerous direct memory access. This reference can be overwritten if anything else modifies memory (!!!). As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data is not overwritten. This function is private to prevent unsafe usage by callers.

function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView);

Parameters

NameTypeDescription
memViewsMemView[]The memory views
locationuint256

Returns

NameTypeDescription
<none>MemViewThe conjoined view pointing to the new memory

Message

Git Source

Message is a memory over over a formatted message payload.

type Message is uint256;

MessageLib

Git Source

Library for formatting the various messages supported by Origin and Destination.

Message memory layout

PositionFieldTypeBytesDescription
[000..017)headeruint13617Encoded general routing information for the message
[017..AAA)bodybytes??Formatted payload (according to flag) with message body

State Variables

OFFSET_HEADER

The variables below are not supposed to be used outside of the library directly.

uint256 private constant OFFSET_HEADER = 0;

OFFSET_BODY

uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;

Functions

formatMessage

Returns formatted message with provided fields.

function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory);

Parameters

NameTypeDescription
header_HeaderEncoded general routing information for the message
body_bytesFormatted payload (according to flag) with message body

Returns

NameTypeDescription
<none>bytesFormatted message

castToMessage

Returns a Message view over for the given payload.

Will revert if the payload is not a message payload.

function castToMessage(bytes memory payload) internal pure returns (Message);

castToMessage

Casts a memory view to a Message view.

Will revert if the memory view is not over a message payload.

function castToMessage(MemView memView) internal pure returns (Message);

isMessage

Checks that a payload is a formatted Message.

function isMessage(MemView memView) internal pure returns (bool);

unwrap

Convenience shortcut for unwrapping a view.

function unwrap(Message message) internal pure returns (MemView);

leaf

Returns message's hash: a leaf to be inserted in the Merkle tree.

function leaf(Message message) internal pure returns (bytes32);

Returns message's encoded header field.

function header(Message message) internal pure returns (Header);

body

Returns message's body field as an untyped memory view.

function body(Message message) internal pure returns (MemView);

_header

Returns message's padded header without checking that it is a valid header.

function _header(MemView memView) private pure returns (uint256);

_body

Returns an untyped memory view over the body field without checking if the whole payload or the body are properly formatted.

function _body(MemView memView) private pure returns (MemView);

Receipt

Git Source

Receipt is a memory view over a formatted "full receipt" payload.

type Receipt is uint256;

ReceiptLib

Git Source

Receipt structure represents a Notary statement that a certain message has been executed in ExecutionHub.

  • It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not included in the receipt.
  • Receipt is signed by a Notary and submitted to Summit in order to initiate the tips distribution for an executed message.
  • If a message execution fails the first time, the finalExecutor field will be set to zero address. In this case, when the message is finally executed successfully, the finalExecutor field will be updated. Both receipts will be considered valid.

Memory layout of Receipt fields

PositionFieldTypeBytesDescription
[000..004)originuint324Domain where message originated
[004..008)destinationuint324Domain where message was executed
[008..040)messageHashbytes3232Hash of the message
[040..072)snapshotRootbytes3232Snapshot root used for proving the message
[072..073)stateIndexuint81Index of state used for the snapshot proof
[073..093)attNotaryaddress20Notary who posted attestation with snapshot root
[093..113)firstExecutoraddress20Executor who performed first valid execution
[113..133)finalExecutoraddress20Executor who successfully executed the message

State Variables

OFFSET_ORIGIN

The variables below are not supposed to be used outside of the library directly.

uint256 private constant OFFSET_ORIGIN = 0;

OFFSET_DESTINATION

uint256 private constant OFFSET_DESTINATION = 4;

OFFSET_MESSAGE_HASH

uint256 private constant OFFSET_MESSAGE_HASH = 8;

OFFSET_SNAPSHOT_ROOT

uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;

OFFSET_STATE_INDEX

uint256 private constant OFFSET_STATE_INDEX = 72;

OFFSET_ATT_NOTARY

uint256 private constant OFFSET_ATT_NOTARY = 73;

OFFSET_FIRST_EXECUTOR

uint256 private constant OFFSET_FIRST_EXECUTOR = 93;

OFFSET_FINAL_EXECUTOR

uint256 private constant OFFSET_FINAL_EXECUTOR = 113;

Functions

formatReceipt

Returns a formatted Receipt payload with provided fields.

function formatReceipt(
    uint32 origin_,
    uint32 destination_,
    bytes32 messageHash_,
    bytes32 snapshotRoot_,
    uint8 stateIndex_,
    address attNotary_,
    address firstExecutor_,
    address finalExecutor_
) internal pure returns (bytes memory);

Parameters

NameTypeDescription
origin_uint32Domain where message originated
destination_uint32Domain where message was executed
messageHash_bytes32Hash of the message
snapshotRoot_bytes32Snapshot root used for proving the message
stateIndex_uint8Index of state used for the snapshot proof
attNotary_addressNotary who posted attestation with snapshot root
firstExecutor_addressExecutor who performed first valid execution attempt
finalExecutor_addressExecutor who successfully executed the message

Returns

NameTypeDescription
<none>bytesFormatted receipt

castToReceipt

Returns a Receipt view over the given payload.

Will revert if the payload is not a receipt.

function castToReceipt(bytes memory payload) internal pure returns (Receipt);

castToReceipt

Casts a memory view to a Receipt view.

Will revert if the memory view is not over a receipt.

function castToReceipt(MemView memView) internal pure returns (Receipt);

isReceipt

Checks that a payload is a formatted Receipt.

function isReceipt(MemView memView) internal pure returns (bool);

hashValid

Returns the hash of an Receipt, that could be later signed by a Notary to signal that the receipt is valid.

function hashValid(Receipt receipt) internal pure returns (bytes32);

hashInvalid

Returns the hash of a Receipt, that could be later signed by a Guard to signal that the receipt is invalid.

function hashInvalid(Receipt receipt) internal pure returns (bytes32);

unwrap

Convenience shortcut for unwrapping a view.

function unwrap(Receipt receipt) internal pure returns (MemView);

equals

Compares two Receipt structures.

function equals(Receipt a, Receipt b) internal pure returns (bool);

origin

Returns receipt's origin field

function origin(Receipt receipt) internal pure returns (uint32);

destination

Returns receipt's destination field

function destination(Receipt receipt) internal pure returns (uint32);

messageHash

Returns receipt's "message hash" field

function messageHash(Receipt receipt) internal pure returns (bytes32);

snapshotRoot

Returns receipt's "snapshot root" field

function snapshotRoot(Receipt receipt) internal pure returns (bytes32);

stateIndex

Returns receipt's "state index" field

function stateIndex(Receipt receipt) internal pure returns (uint8);

attNotary

Returns receipt's "attestation notary" field

function attNotary(Receipt receipt) internal pure returns (address);

firstExecutor

Returns receipt's "first executor" field

function firstExecutor(Receipt receipt) internal pure returns (address);

finalExecutor

Returns receipt's "final executor" field

function finalExecutor(Receipt receipt) internal pure returns (address);

Snapshot

Git Source

Snapshot is a memory view over a formatted snapshot payload: a list of states.

type Snapshot is uint256;

SnapshotLib

Git Source

Snapshot

Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains. In short, snapshot is a list of "State" structs. See State.sol for details about the "State" structs.

Snapshot usage

  • Both Guards and Notaries are supposed to form snapshots and sign snapshot.hash() to verify its validity.
  • Each Guard should be monitoring a set of Origin contracts chosen as they see fit.
  • They are expected to form snapshots with Origin states for this set of chains, sign and submit them to Summit contract.
  • Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.
  • They should be forming their own snapshots using states from snapshots of any of the Guards.
  • The states for the Notary snapshots don't have to come from the same Guard snapshot, or don't even have to be submitted by the same Guard.
  • With their signature, Notary effectively "notarizes" the work that some Guards have done in Summit contract.
  • Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as a proof of liveliness for Guards monitoring these Origins.

Snapshot validity

  • Snapshot is considered "valid" in Origin, if every state referring to that Origin is valid there.
  • Snapshot is considered "globally valid", if it is "valid" in every Origin contract.

Snapshot memory layout

PositionFieldTypeBytesDescription
[000..050)states[0]bytes50Origin State with index==0
[050..100)states[1]bytes50Origin State with index==1
.........50...
[AAA..BBB)states[N-1]bytes50Origin State with index==N-1

Snapshot could be signed by both Guards and Notaries and submitted to Summit in order to produce Attestations that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.

Functions

formatSnapshot

Returns a formatted Snapshot payload using a list of States.

function formatSnapshot(State[] memory states) internal view returns (bytes memory);

Parameters

NameTypeDescription
statesState[]Arrays of State-typed memory views over Origin states

Returns

NameTypeDescription
<none>bytesFormatted snapshot

castToSnapshot

Returns a Snapshot view over for the given payload.

Will revert if the payload is not a snapshot payload.

function castToSnapshot(bytes memory payload) internal pure returns (Snapshot);

castToSnapshot

Casts a memory view to a Snapshot view.

Will revert if the memory view is not over a snapshot payload.

function castToSnapshot(MemView memView) internal pure returns (Snapshot);

isSnapshot

Checks that a payload is a formatted Snapshot.

function isSnapshot(MemView memView) internal pure returns (bool);

hashValid

Returns the hash of a Snapshot, that could be later signed by an Agent to signal that the snapshot is valid.

function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot);

unwrap

Convenience shortcut for unwrapping a view.

function unwrap(Snapshot snapshot) internal pure returns (MemView);

state

Returns a state with a given index from the snapshot.

function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State);

statesAmount

Returns the amount of states in the snapshot.

function statesAmount(Snapshot snapshot) internal pure returns (uint256);

snapGas

Extracts the list of ChainGas structs from the snapshot.

function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_);

calculateRoot

Returns the root for the "Snapshot Merkle Tree" composed of state leafs from the snapshot.

function calculateRoot(Snapshot snapshot) internal pure returns (bytes32);

proofSnapRoot

Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain) and proof of inclusion of State Merkle Data (aka State "left sub-leaf") in Snapshot Merkle Tree.

Reverts if any of these is true:

  • State index is out of range.
  • Snapshot Proof length exceeds Snapshot tree Height.
function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)
    internal
    pure
    returns (bytes32);

Parameters

NameTypeDescription
originRootbytes32Root of Origin Merkle Tree
domainuint32Domain of Origin chain
snapProofbytes32[]Proof of inclusion of State Merkle Data into Snapshot Merkle Tree
stateIndexuint8Index of Origin State in the Snapshot

_isValidAmount

Checks if snapshot's states amount is valid.

function _isValidAmount(uint256 statesAmount_) internal pure returns (bool);

State

Git Source

State is a memory view over a formatted state payload.

type State is uint256;

StateLib

Git Source

State

State structure represents the state of Origin contract at some point of time.

  • State is structured in a way to track the updates of the Origin Merkle Tree.
  • State includes root of the Origin Merkle Tree, origin domain and some additional metadata.

Origin Merkle Tree

Hash of every sent message is inserted in the Origin Merkle Tree, which changes the value of Origin Merkle Root (which is the root for the mentioned tree).

  • Origin has a single Merkle Tree for all messages, regardless of their destination domain.
  • This leads to Origin state being updated if and only if a message was sent in a block.
  • Origin contract is a "source of truth" for states: a state is considered "valid" in its Origin, if it matches the state of the Origin contract after the N-th (nonce) message was sent.

Memory layout of State fields

PositionFieldTypeBytesDescription
[000..032)rootbytes3232Root of the Origin Merkle Tree
[032..036)originuint324Domain where Origin is located
[036..040)nonceuint324Amount of sent messages
[040..045)blockNumberuint405Block of last sent message
[045..050)timestampuint405Time of last sent message
[050..062)gasDatauint9612Gas data for the chain

State could be used to form a Snapshot to be signed by a Guard or a Notary.

State Variables

OFFSET_ROOT

The variables below are not supposed to be used outside of the library directly.

uint256 private constant OFFSET_ROOT = 0;

OFFSET_ORIGIN

uint256 private constant OFFSET_ORIGIN = 32;

OFFSET_NONCE

uint256 private constant OFFSET_NONCE = 36;

OFFSET_BLOCK_NUMBER

uint256 private constant OFFSET_BLOCK_NUMBER = 40;

OFFSET_TIMESTAMP

uint256 private constant OFFSET_TIMESTAMP = 45;

OFFSET_GAS_DATA

uint256 private constant OFFSET_GAS_DATA = 50;

Functions

formatState

Returns a formatted State payload with provided fields

function formatState(
    bytes32 root_,
    uint32 origin_,
    uint32 nonce_,
    uint40 blockNumber_,
    uint40 timestamp_,
    GasData gasData_
) internal pure returns (bytes memory);

Parameters

NameTypeDescription
root_bytes32New merkle root
origin_uint32Domain of Origin's chain
nonce_uint32Nonce of the merkle root
blockNumber_uint40Block number when root was saved in Origin
timestamp_uint40Block timestamp when root was saved in Origin
gasData_GasDataGas data for the chain

Returns

NameTypeDescription
<none>bytesFormatted state

castToState

Returns a State view over the given payload.

Will revert if the payload is not a state.

function castToState(bytes memory payload) internal pure returns (State);

castToState

Casts a memory view to a State view.

Will revert if the memory view is not over a state.

function castToState(MemView memView) internal pure returns (State);

isState

Checks that a payload is a formatted State.

function isState(MemView memView) internal pure returns (bool);

hashInvalid

Returns the hash of a State, that could be later signed by a Guard to signal that the state is invalid.

function hashInvalid(State state) internal pure returns (bytes32);

unwrap

Convenience shortcut for unwrapping a view.

function unwrap(State state) internal pure returns (MemView);

equals

Compares two State structures.

function equals(State a, State b) internal pure returns (bool);

leaf

Returns the hash of the State.

We are using the Merkle Root of a tree with two leafs (see below) as state hash.

function leaf(State state) internal pure returns (bytes32);

subLeafs

Returns "sub-leafs" of the State. Hash of these "sub leafs" is going to be used as a "state leaf" in the "Snapshot Merkle Tree". This enables proving that leftLeaf = (root, origin) was a part of the "Snapshot Merkle Tree", by combining rightLeaf with the remainder of the "Snapshot Merkle Proof".

function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_);

leftLeaf

Returns the left "sub-leaf" of the State.

function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32);

rightLeaf

Returns the right "sub-leaf" of the State.

function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)
    internal
    pure
    returns (bytes32);

root

Returns a historical Merkle root from the Origin contract.

function root(State state) internal pure returns (bytes32);

origin

Returns domain of chain where the Origin contract is deployed.

function origin(State state) internal pure returns (uint32);

nonce

Returns nonce of Origin contract at the time, when root was the Merkle root.

function nonce(State state) internal pure returns (uint32);

blockNumber

Returns a block number when root was saved in Origin.

function blockNumber(State state) internal pure returns (uint40);

timestamp

Returns a block timestamp when root was saved in Origin.

This is the timestamp according to the origin chain.

function timestamp(State state) internal pure returns (uint40);

gasData

Returns gas data for the chain.

function gasData(State state) internal pure returns (GasData);

Contents

MerkleMath

Git Source

Functions

proofRoot

Calculates the merkle root for the given leaf and merkle proof.

Will revert if proof length exceeds the tree height.

function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)
    internal
    pure
    returns (bytes32 root_);

Parameters

NameTypeDescription
indexuint256Index of leaf in tree
leafbytes32Leaf of the merkle tree
proofbytes32[]Proof of inclusion of leaf in the tree
heightuint256Height of the merkle tree

Returns

NameTypeDescription
root_bytes32Calculated Merkle Root

getParent

Calculates the parent of a node on the path from one of the leafs to root.

Apply unchecked to all ++h operations

function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)
    internal
    pure
    returns (bytes32 parent);

Parameters

NameTypeDescription
nodebytes32Node on a path from tree leaf to root
siblingbytes32Sibling for a given node
leafIndexuint256Index of the tree leaf
nodeHeightuint256"Level height" for node (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)

getParent

Calculates the parent of tow nodes in the merkle tree.

We use implementation with H(0,0) = 0 This makes EVERY empty node in the tree equal to ZERO, saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on

function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent);

Parameters

NameTypeDescription
leftChildbytes32Left child of the calculated node
rightChildbytes32Right child of the calculated node

Returns

NameTypeDescription
parentbytes32Value for the node having above mentioned children

calculateRoot

Calculates merkle root for a list of given leafs. Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is 2**height. Merkle Root is calculated for the constructed tree, and then saved in leafs[0].

Note:

  • leafs values are overwritten in the process to avoid excessive memory allocations.
  • Caller is expected not to reuse hashes list after the call, and only use leafs[0] value, which is guaranteed to contain the calculated merkle root.
  • root is calculated using the H(0,0) = 0 Merkle Tree implementation. See MerkleTree.sol for details.

Amount of leaves should be at most 2**height

function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure;

Parameters

NameTypeDescription
hashesbytes32[]List of leafs for the merkle tree (to be overwritten)
heightuint256Height of the Merkle Tree to construct

calculateProof

Generates a proof of inclusion of a leaf in the list. If the requested index is outside of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion). The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two AND index is in the extended list range. For example:

  • hashes.length == 6 and 0 <= index <= 7 will "extend" the list to 8 entries.
  • hashes.length == 6 and 7 < index <= 15 will "extend" the list to 16 entries.

Note: leafs values are overwritten in the process to avoid excessive memory allocations. Caller is expected not to reuse hashes list after the call.

h, leftIndex, rightIndex and levelLength never overflow

function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof);

Parameters

NameTypeDescription
hashesbytes32[]List of leafs for the merkle tree (to be overwritten)
indexuint256Leaf index to generate the proof for

Returns

NameTypeDescription
proofbytes32[]Generated merkle proof

getHeight

Returns the height of the tree having a given amount of leafs.

h, leftIndex, rightIndex and levelLength never overflow

function getHeight(uint256 leafs) internal pure returns (uint256 height);

BaseTree

Git Source

BaseTree is a struct representing incremental merkle tree.

  • Contains only the current branch.
  • The number of inserted leaves is stored externally, and is later supplied for tree operations.
  • Has a fixed height of ORIGIN_TREE_HEIGHT.
  • Can store up to 2 ** ORIGIN_TREE_HEIGHT - 1 leaves.

Note: the hash function for the tree H(x, y) is defined as:

  • H(0,0) = 0
  • H(x,y) = keccak256(x, y), when (x != 0 || y != 0)

Invariant for leafs

  • The leftmost empty leaf has index == count, where count is the amount of the inserted leafs so far.
  • Value for any empty leaf or node is bytes32(0).

Invariant for current branch

branch[i] is always the value of a node on the i-th level. Levels are numbered from leafs to root: 0 .. ORIGIN_TREE_HEIGHT. branch[i] stores the value for the node, such that:

  • The node must have two non-empty children.
  • Out of all level's "left child" nodes with "non-empty children", the one with the biggest index (the rightmost one) is stored as branch[i].

branch could be used to form a proof of inclusion for the first empty leaf (index == count). Here is how:

  • Let's walk along the path from the "first empty leaf" to the root.
  • i-th bit of the "first empty leaf" index (which is equal to count) determines if the path's node for this i-th level is a "left child" or a "right child".
  • i-th bit in count is 0 → we are the left child on this level → sibling is the right child that does not exist yet → proof[i] = bytes32(0).
  • i-th bit in count is 1 → we are the right child on this level → sibling is the left child sibling is the rightmost "left child" node on the level → proof[i] = branch[i].

Therefore proof[i] = (count & (1 << i)) == 0 ? bytes32(0) : branch[i])

struct BaseTree {
    bytes32[ORIGIN_TREE_HEIGHT] branch;
}

HistoricalTree

Git Source

HistoricalTree is an incremental merkle tree keeping track of its historical merkle roots.

  • roots[N] is the root of the tree after N leafs were inserted
  • roots[0] == bytes32(0)
struct HistoricalTree {
    BaseTree tree;
    bytes32[] roots;
}

DynamicTree

Git Source

DynamicTree is a struct representing a Merkle Tree with 2**AGENT_TREE_HEIGHT leaves.

  • A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).
  • This is done by requesting the proof of inclusion for the old value, which is used to both verify the old value, and calculate the new root.

Based on Original idea from ER forum post.

struct DynamicTree {
    bytes32 root;
}

MerkleTree

Git Source

MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0 link. With the following changes:

  • Adapted for Solidity 0.8.x.
  • Amount of tree leaves stored externally.
  • Added thorough documentation.
  • H(0,0) = 0 optimization from ER forum post.

Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0 link. With the following changes:

  • Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).
  • H() = keccak256() is used as the hashing function instead of sha256().

State Variables

MAX_LEAVES

For root calculation we need at least one empty leaf, thus the minus one in the formula.

uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;

Functions

insertBase

Inserts node into merkle tree

Reverts if tree is full

function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal;

Parameters

NameTypeDescription
treeBaseTree
newCountuint256Amount of inserted leaves in the tree after the insertion (i.e. current + 1)
nodebytes32Element to insert into tree

rootBase

Calculates and returns current root of the merkle tree.

function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current);

Parameters

NameTypeDescription
treeBaseTree
countuint256Current amount of inserted leaves in the tree

Returns

NameTypeDescription
currentbytes32Calculated root of tree

initializeRoots

Initializes the historical roots for the tree by inserting an empty root.

function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot);

insert

Inserts a new leaf into the merkle tree.

Reverts if tree is full.

function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot);

Parameters

NameTypeDescription
treeHistoricalTree
nodebytes32Element to insert into tree

Returns

NameTypeDescription
newRootbytes32Merkle root after the leaf was inserted

root

Returns the historical root of the merkle tree.

Reverts if not enough leafs have been inserted.

function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot);

Parameters

NameTypeDescription
treeHistoricalTree
countuint256Amount of leafs in the tree at some point of time

Returns

NameTypeDescription
historicalRootbytes32Merkle root after count leafs were inserted

update

Updates the value for the leaf with the given index in the Dynamic Merkle Tree.

Will revert if incorrect proof of inclusion for old value is supplied.

function update(DynamicTree storage tree, uint256 index, bytes32 oldValue, bytes32[] memory branch, bytes32 newValue)
    internal
    returns (bytes32 newRoot);

Parameters

NameTypeDescription
treeDynamicTreeDynamic merkle tree
indexuint256Index of the leaf to update
oldValuebytes32Previous value of the leaf
branchbytes32[]Proof of inclusion of previous value into the tree
newValuebytes32New leaf value to assign

Returns

NameTypeDescription
newRootbytes32New value for the Merkle Root after the leaf is updated

Contents

GasData

Git Source

GasData in encoded data with "basic information about gas prices" for some chain.

type GasData is uint96;

ChainGas

Git Source

ChainGas is encoded data with given chain's "basic information about gas prices".

type ChainGas is uint128;

GasDataLib

Git Source

Library for encoding and decoding GasData and ChainGas structs.

GasData

GasData is a struct to store the "basic information about gas prices", that could be later used to approximate the cost of a message execution, and thus derive the minimal tip values for sending a message to the chain.

  • GasData is supposed to be cached by GasOracle contract, allowing to store the approximates instead of the exact values, and thus save on storage costs.
  • For instance, if GasOracle only updates the values on +- 10% change, having an 0.4% error on the approximates would be acceptable. GasData is supposed to be included in the Origin's state, which are synced across chains using Agent-signed snapshots and attestations.

GasData stack layout (from highest bits to lowest)

PositionFieldTypeBytesDescription
(012..010]gasPriceuint162Gas price for the chain (in Wei per gas unit)
(010..008]dataPriceuint162Calldata price (in Wei per byte of content)
(008..006]execBufferuint162Tx fee safety buffer for message execution (in Wei)
(006..004]amortAttCostuint162Amortized cost for attestation submission (in Wei)
(004..002]etherPriceuint162Chain's Ether Price / Mainnet Ether Price (in BWAD)
(002..000]markupuint162Markup for the message execution (in BWAD)

See Number.sol for more details on Number type and BWAD (binary WAD) math.

ChainGas stack layout (from highest bits to lowest)

PositionFieldTypeBytesDescription
(016..004]gasDatauint9612Chain's gas data
(004..000]domainuint324Chain's domain

State Variables

SHIFT_GAS_PRICE

Amount of bits to shift to gasPrice field

uint96 private constant SHIFT_GAS_PRICE = 10 * 8;

SHIFT_DATA_PRICE

Amount of bits to shift to dataPrice field

uint96 private constant SHIFT_DATA_PRICE = 8 * 8;

SHIFT_EXEC_BUFFER

Amount of bits to shift to execBuffer field

uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;

SHIFT_AMORT_ATT_COST

Amount of bits to shift to amortAttCost field

uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;

SHIFT_ETHER_PRICE

Amount of bits to shift to etherPrice field

uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;

SHIFT_GAS_DATA

Amount of bits to shift to gasData field

uint128 private constant SHIFT_GAS_DATA = 4 * 8;

Functions

encodeGasData

Returns an encoded GasData struct with the given fields.

function encodeGasData(
    Number gasPrice_,
    Number dataPrice_,
    Number execBuffer_,
    Number amortAttCost_,
    Number etherPrice_,
    Number markup_
) internal pure returns (GasData);

Parameters

NameTypeDescription
gasPrice_NumberGas price for the chain (in Wei per gas unit)
dataPrice_NumberCalldata price (in Wei per byte of content)
execBuffer_NumberTx fee safety buffer for message execution (in Wei)
amortAttCost_NumberAmortized cost for attestation submission (in Wei)
etherPrice_NumberRatio of Chain's Ether Price / Mainnet Ether Price (in BWAD)
markup_NumberMarkup for the message execution (in BWAD)

wrapGasData

Wraps padded uint256 value into GasData struct.

function wrapGasData(uint256 paddedGasData) internal pure returns (GasData);

gasPrice

Returns the gas price, in Wei per gas unit.

function gasPrice(GasData data) internal pure returns (Number);

dataPrice

Returns the calldata price, in Wei per byte of content.

function dataPrice(GasData data) internal pure returns (Number);

execBuffer

Returns the tx fee safety buffer for message execution, in Wei.

function execBuffer(GasData data) internal pure returns (Number);

amortAttCost

Returns the amortized cost for attestation submission, in Wei.

function amortAttCost(GasData data) internal pure returns (Number);

etherPrice

Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.

function etherPrice(GasData data) internal pure returns (Number);

markup

Returns the markup for the message execution, in BWAD math.

function markup(GasData data) internal pure returns (Number);

encodeChainGas

Returns an encoded ChainGas struct with the given fields.

function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas);

Parameters

NameTypeDescription
gasData_GasDataChain's gas data
domain_uint32Chain's domain

wrapChainGas

Wraps padded uint256 value into ChainGas struct.

function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas);

gasData

Returns the chain's gas data.

function gasData(ChainGas data) internal pure returns (GasData);

domain

Returns the chain's domain.

function domain(ChainGas data) internal pure returns (uint32);

snapGasHash

Returns the hash for the list of ChainGas structs.

function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_);

Header

Git Source

Header is encoded data with "general routing information".

type Header is uint136;

MessageFlag

Git Source

Types of messages supported by Origin-Destination

  • Base: message sent by protocol user, contains tips
  • Manager: message sent between AgentManager contracts located on different chains, no tips
enum MessageFlag {
    Base,
    Manager
}

HeaderLib

Git Source

Library for formatting the header part of the messages used by Origin and Destination.

  • Header represents general information for routing a Message for Origin and Destination.
  • Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.

Header stack layout (from highest bits to lowest)

PositionFieldTypeBytesDescription
(017..016]flaguint81Flag specifying the type of message
(016..012]originuint324Domain where message originated
(012..008]nonceuint324Message nonce on the origin domain
(008..004]destinationuint324Domain where message will be executed
(004..000]optimisticPerioduint324Optimistic period that will be enforced

State Variables

SHIFT_FLAG

Amount of bits to shift to flag field

uint136 private constant SHIFT_FLAG = 16 * 8;

SHIFT_ORIGIN

Amount of bits to shift to origin field

uint136 private constant SHIFT_ORIGIN = 12 * 8;

SHIFT_NONCE

Amount of bits to shift to nonce field

uint136 private constant SHIFT_NONCE = 8 * 8;

SHIFT_DESTINATION

Amount of bits to shift to destination field

uint136 private constant SHIFT_DESTINATION = 4 * 8;

Functions

encodeHeader

Returns an encoded header with provided fields

function encodeHeader(MessageFlag flag_, uint32 origin_, uint32 nonce_, uint32 destination_, uint32 optimisticPeriod_)
    internal
    pure
    returns (Header);

Parameters

NameTypeDescription
flag_MessageFlag
origin_uint32Domain of origin chain
nonce_uint32Message nonce on origin chain
destination_uint32Domain of destination chain
optimisticPeriod_uint32Optimistic period for message execution

isHeader

Checks that the header is a valid encoded header.

function isHeader(uint256 paddedHeader) internal pure returns (bool);

wrapPadded

Wraps the padded encoded request into a Header-typed value.

The "padded" header is simply an encoded header casted to uint256 (highest bits are set to zero). Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed. The highest bits are discarded, so that the contracts dealing with encoded headers don't need to be updated, if a new field is added.

function wrapPadded(uint256 paddedHeader) internal pure returns (Header);

leaf

Returns header's hash: a leaf to be inserted in the "Message mini-Merkle tree".

function leaf(Header header) internal pure returns (bytes32 hashedHeader);

flag

Returns header's flag field

function flag(Header header) internal pure returns (MessageFlag);

origin

Returns header's origin field

function origin(Header header) internal pure returns (uint32);

nonce

Returns header's nonce field

function nonce(Header header) internal pure returns (uint32);

destination

Returns header's destination field

function destination(Header header) internal pure returns (uint32);

optimisticPeriod

Returns header's optimistic seconds field

function optimisticPeriod(Header header) internal pure returns (uint32);

_flag

Returns header's flag field without casting to MessageFlag

function _flag(uint256 paddedHeader) private pure returns (uint8);

Number

Git Source

Number is a compact representation of uint256, that is fit into 16 bits with the maximum relative error under 0.4%.

type Number is uint16;

NumberLib

Git Source

Number

Library for compact representation of uint256 numbers.

  • Number is stored using mantissa and exponent, each occupying 8 bits.
  • Numbers under 2**8 are stored as mantissa with exponent = 0xFF.
  • Numbers at least 2**8 are approximated as (256 + mantissa) << exponent
  • 0 <= mantissa < 256
  • 0 <= exponent <= 247 (256 * 2**248 doesn't fit into uint256)

Number stack layout (from highest bits to lowest)

PositionFieldTypeBytes
(002..001]mantissauint81
(001..000]exponentuint81

State Variables

SHIFT_MANTISSA

Amount of bits to shift to mantissa field

uint16 private constant SHIFT_MANTISSA = 8;

BWAD_SHIFT

For bwad math (binary wad) we use 2**64 as "wad" unit.

We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.

uint256 internal constant BWAD_SHIFT = 64;

BWAD

uint256 internal constant BWAD = 1 << BWAD_SHIFT;

PER_MILLE_SHIFT

~0.1% in bwad units.

uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;

PER_MILLE

uint256 internal constant PER_MILLE = 1 << PER_MILLE_SHIFT;

Functions

compress

Compresses uint256 number into 16 bits.

function compress(uint256 value) internal pure returns (Number);

decompress

Decompresses 16 bits number into uint256.

The outcome is an approximation of the original number: (value - value / 256) < number <= value.

function decompress(Number number) internal pure returns (uint256 value);

mostSignificantBit

Returns the most significant bit of x https://solidity-by-example.org/bitwise/

function mostSignificantBit(uint256 x) internal pure returns (uint256 msb);

_encode

Wraps (mantissa, exponent) pair into Number.

function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number);

Request

Git Source

Request is encoded data with "message execution request".

type Request is uint192;

RequestLib

Git Source

Library for formatting the request part of the base messages.

  • Request represents a message sender requirements for the message execution on the destination chain.
  • Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.

gasDrop field is included for future compatibility and is ignored at the moment.

Request stack layout (from highest bits to lowest)

PositionFieldTypeBytesDescription
(024..012]gasDropuint9612Minimum amount of gas token to drop to the recipient
(012..004]gasLimituint648Minimum amount of gas units to supply for execution
(004..000]versionuint324Base message version to pass to the recipient

State Variables

SHIFT_GAS_DROP

Amount of bits to shift to gasDrop field

uint192 private constant SHIFT_GAS_DROP = 12 * 8;

SHIFT_GAS_LIMIT

Amount of bits to shift to gasLimit field

uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;

Functions

encodeRequest

Returns an encoded request with the given fields

function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request);

Parameters

NameTypeDescription
gasDrop_uint96Minimum amount of gas token to drop to the recipient (ignored at the moment)
gasLimit_uint64Minimum amount of gas units to supply for execution
version_uint32Base message version to pass to the recipient

wrapPadded

Wraps the padded encoded request into a Request-typed value.

The "padded" request is simply an encoded request casted to uint256 (highest bits are set to zero). Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed. The highest bits are discarded, so that the contracts dealing with encoded requests don't need to be updated, if a new field is added.

function wrapPadded(uint256 paddedRequest) internal pure returns (Request);

gasDrop

Returns the requested of gas token to drop to the recipient.

function gasDrop(Request request) internal pure returns (uint96);

gasLimit

Returns the requested minimum amount of gas units to supply for execution.

function gasLimit(Request request) internal pure returns (uint64);

version

Returns the requested base message version to pass to the recipient.

function version(Request request) internal pure returns (uint32);

Tips

Git Source

Tips is encoded data with "tips paid for sending a base message". Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.

type Tips is uint256;

TipsLib

Git Source

Tips

Library for formatting the tips part of the base messages.

How the tips are awarded

Tips are paid for sending a base message, and are split across all the agents that made the message execution on destination chain possible.

Summit tips

Split between:

  • Guard posting a snapshot with state ST_G for the origin chain.
  • Notary posting a snapshot SN_N using ST_G. This creates attestation A.
  • Notary posting a message receipt after it is executed on destination chain.

Attestation tips

Paid to:

  • Notary posting attestation A to destination chain.

Execution tips

Paid to:

  • First executor performing a valid execution attempt (correct proofs, optimistic period over), using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.

Delivery tips.

Paid to:

  • Executor who successfully executed the message on destination chain.

Tips encoding

  • Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.
  • The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.
  • Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.

The only downside is that the "real tip values" are now multiplies of ~4*10**9, which should be fine even for the chains with the most expensive gas currency.

Tips stack layout (from highest bits to lowest)

PositionFieldTypeBytesDescription
(032..024]summitTipuint648Tip for agents interacting with Summit contract
(024..016]attestationTipuint648Tip for Notary posting attestation to Destination contract
(016..008]executionTipuint648Tip for valid execution attempt on destination chain
(008..000]deliveryTipuint648Tip for successful message delivery on destination chain

State Variables

SHIFT_SUMMIT_TIP

Amount of bits to shift to summitTip field

uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;

SHIFT_ATTESTATION_TIP

Amount of bits to shift to attestationTip field

uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;

SHIFT_EXECUTION_TIP

Amount of bits to shift to executionTip field

uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;

Functions

encodeTips

Returns encoded tips with the given fields

function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)
    internal
    pure
    returns (Tips);

Parameters

NameTypeDescription
summitTip_uint64Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER
attestationTip_uint64Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER
executionTip_uint64Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER
deliveryTip_uint64Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER

encodeTips256

Convenience function to encode tips with uint256 values.

function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)
    internal
    pure
    returns (Tips);

wrapPadded

Wraps the padded encoded tips into a Tips-typed value.

There is no actual padding here, as the underlying type is already uint256, but we include this function for consistency and to be future-proof, if tips will eventually use anything smaller than uint256.

function wrapPadded(uint256 paddedTips) internal pure returns (Tips);

emptyTips

Returns a formatted Tips payload specifying empty tips.

function emptyTips() internal pure returns (Tips);

Returns

NameTypeDescription
<none>TipsFormatted tips

leaf

Returns tips's hash: a leaf to be inserted in the "Message mini-Merkle tree".

function leaf(Tips tips) internal pure returns (bytes32 hashedTips);

summitTip

Returns summitTip field

function summitTip(Tips tips) internal pure returns (uint64);

attestationTip

Returns attestationTip field

function attestationTip(Tips tips) internal pure returns (uint64);

executionTip

Returns executionTip field

function executionTip(Tips tips) internal pure returns (uint64);

deliveryTip

Returns deliveryTip field

function deliveryTip(Tips tips) internal pure returns (uint64);

value

Returns total value of the tips payload. This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER

function value(Tips tips) internal pure returns (uint256 value_);

matchValue

Increases the delivery tip to match the new value.

function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips);

ChainContext

Git Source

Library for accessing chain context variables as tightly packed integers. Messaging contracts should rely on this library for accessing chain context variables instead of doing the casting themselves.

Functions

blockNumber

Returns the current block number as uint40.

Reverts if block number is greater than 40 bits, which is not supposed to happen until the block.timestamp overflows (assuming block time is at least 1 second).

function blockNumber() internal view returns (uint40);

blockTimestamp

Returns the current block timestamp as uint40.

Reverts if block timestamp is greater than 40 bits, which is supposed to happen approximately in year 36835.

function blockTimestamp() internal view returns (uint40);

chainId

Returns the chain id as uint32.

Reverts if chain id is greater than 32 bits, which is not supposed to happen in production.

function chainId() internal view returns (uint32);

Constants

Git Source

AGENT_TREE_HEIGHT

Height of the Agent Merkle Tree

uint256 constant AGENT_TREE_HEIGHT = 32;

ORIGIN_TREE_HEIGHT

Height of the Origin Merkle Tree

uint256 constant ORIGIN_TREE_HEIGHT = 32;

SNAPSHOT_TREE_HEIGHT

Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states

uint256 constant SNAPSHOT_TREE_HEIGHT = 6;

ATTESTATION_LENGTH

See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5

uint256 constant ATTESTATION_LENGTH = 78;

GAS_DATA_LENGTH

See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2

uint256 constant GAS_DATA_LENGTH = 12;

RECEIPT_LENGTH

See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20

uint256 constant RECEIPT_LENGTH = 133;

STATE_LENGTH

See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)

uint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;

SNAPSHOT_MAX_STATES

Maximum amount of states in a single snapshot. Each state produces two leafs in the tree

uint256 constant SNAPSHOT_MAX_STATES = 1 << (SNAPSHOT_TREE_HEIGHT - 1);

HEADER_LENGTH

See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4

uint256 constant HEADER_LENGTH = 17;

REQUEST_LENGTH

See Request.sol: (uint96,uint64,uint32): 12+8+4

uint256 constant REQUEST_LENGTH = 24;

TIPS_LENGTH

See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8

uint256 constant TIPS_LENGTH = 32;

TIPS_GRANULARITY

The amount of discarded last bits when encoding tip values

uint256 constant TIPS_GRANULARITY = 32;

TIPS_MULTIPLIER

Tip values could be only the multiples of TIPS_MULTIPLIER

uint256 constant TIPS_MULTIPLIER = 1 << TIPS_GRANULARITY;

ATTESTATION_VALID_SALT

Salts for signing various statements

bytes32 constant ATTESTATION_VALID_SALT = keccak256("ATTESTATION_VALID_SALT");

ATTESTATION_INVALID_SALT

bytes32 constant ATTESTATION_INVALID_SALT = keccak256("ATTESTATION_INVALID_SALT");

RECEIPT_VALID_SALT

bytes32 constant RECEIPT_VALID_SALT = keccak256("RECEIPT_VALID_SALT");

RECEIPT_INVALID_SALT

bytes32 constant RECEIPT_INVALID_SALT = keccak256("RECEIPT_INVALID_SALT");

SNAPSHOT_VALID_SALT

bytes32 constant SNAPSHOT_VALID_SALT = keccak256("SNAPSHOT_VALID_SALT");

STATE_INVALID_SALT

bytes32 constant STATE_INVALID_SALT = keccak256("STATE_INVALID_SALT");

AGENT_ROOT_OPTIMISTIC_PERIOD

Optimistic period for new agent roots in LightManager

uint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;

AGENT_ROOT_PROPOSAL_TIMEOUT

Timeout between the agent root could be proposed and resolved in LightManager

uint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;

BONDING_OPTIMISTIC_PERIOD

uint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;

DISPUTE_TIMEOUT_NOTARY

Amount of time that the Notary will not be considered active after they won a dispute

uint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;

FRESH_DATA_TIMEOUT

Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually

uint256 constant FRESH_DATA_TIMEOUT = 4 hours;

MAX_CONTENT_BYTES

Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)

uint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;

MAX_SUMMIT_TIP

Maximum value for the summit tip that could be set in GasOracle

uint256 constant MAX_SUMMIT_TIP = 0.01 ether;

CallerNotAgentManager

Git Source

error CallerNotAgentManager();

CallerNotDestination

Git Source

error CallerNotDestination();

CallerNotInbox

Git Source

error CallerNotInbox();

CallerNotSummit

Git Source

error CallerNotSummit();

IncorrectAttestation

Git Source

error IncorrectAttestation();

IncorrectAgentDomain

Git Source

error IncorrectAgentDomain();

IncorrectAgentIndex

Git Source

error IncorrectAgentIndex();

IncorrectAgentProof

Git Source

error IncorrectAgentProof();

IncorrectAgentRoot

Git Source

error IncorrectAgentRoot();

IncorrectDataHash

Git Source

error IncorrectDataHash();

IncorrectDestinationDomain

Git Source

error IncorrectDestinationDomain();

IncorrectOriginDomain

Git Source

error IncorrectOriginDomain();

IncorrectSnapshotProof

Git Source

error IncorrectSnapshotProof();

IncorrectSnapshotRoot

Git Source

error IncorrectSnapshotRoot();

IncorrectState

Git Source

error IncorrectState();

IncorrectStatesAmount

Git Source

error IncorrectStatesAmount();

IncorrectTipsProof

Git Source

error IncorrectTipsProof();

IncorrectVersionLength

Git Source

error IncorrectVersionLength();

IncorrectNonce

Git Source

error IncorrectNonce();

IncorrectSender

Git Source

error IncorrectSender();

IncorrectRecipient

Git Source

error IncorrectRecipient();

FlagOutOfRange

Git Source

error FlagOutOfRange();

IndexOutOfRange

Git Source

error IndexOutOfRange();

NonceOutOfRange

Git Source

error NonceOutOfRange();

OutdatedNonce

Git Source

error OutdatedNonce();

UnformattedAttestation

Git Source

error UnformattedAttestation();

UnformattedAttestationReport

Git Source

error UnformattedAttestationReport();

UnformattedBaseMessage

Git Source

error UnformattedBaseMessage();

UnformattedCallData

Git Source

error UnformattedCallData();

UnformattedCallDataPrefix

Git Source

error UnformattedCallDataPrefix();

UnformattedMessage

Git Source

error UnformattedMessage();

UnformattedReceipt

Git Source

error UnformattedReceipt();

UnformattedReceiptReport

Git Source

error UnformattedReceiptReport();

UnformattedSignature

Git Source

error UnformattedSignature();

UnformattedSnapshot

Git Source

error UnformattedSnapshot();

UnformattedState

Git Source

error UnformattedState();

UnformattedStateReport

Git Source

error UnformattedStateReport();

LeafNotProven

Git Source

error LeafNotProven();

MerkleTreeFull

Git Source

error MerkleTreeFull();

NotEnoughLeafs

Git Source

error NotEnoughLeafs();

TreeHeightTooLow

Git Source

error TreeHeightTooLow();

BaseClientOptimisticPeriod

Git Source

error BaseClientOptimisticPeriod();

MessageOptimisticPeriod

Git Source

error MessageOptimisticPeriod();

SlashAgentOptimisticPeriod

Git Source

error SlashAgentOptimisticPeriod();

WithdrawTipsOptimisticPeriod

Git Source

error WithdrawTipsOptimisticPeriod();

ZeroProofMaturity

Git Source

error ZeroProofMaturity();

AgentNotGuard

Git Source

error AgentNotGuard();

AgentNotNotary

Git Source

error AgentNotNotary();

AgentCantBeAdded

Git Source

error AgentCantBeAdded();

AgentNotActive

Git Source

error AgentNotActive();

AgentNotActiveNorUnstaking

Git Source

error AgentNotActiveNorUnstaking();

AgentNotFraudulent

Git Source

error AgentNotFraudulent();

AgentNotUnstaking

Git Source

error AgentNotUnstaking();

AgentUnknown

Git Source

error AgentUnknown();

AgentRootNotProposed

Git Source

error AgentRootNotProposed();

AgentRootTimeoutNotOver

Git Source

error AgentRootTimeoutNotOver();

NotStuck

Git Source

error NotStuck();

DisputeAlreadyResolved

Git Source

error DisputeAlreadyResolved();

DisputeNotOpened

Git Source

error DisputeNotOpened();

DisputeTimeoutNotOver

Git Source

error DisputeTimeoutNotOver();

GuardInDispute

Git Source

error GuardInDispute();

NotaryInDispute

Git Source

error NotaryInDispute();

MustBeSynapseDomain

Git Source

error MustBeSynapseDomain();

SynapseDomainForbidden

Git Source

error SynapseDomainForbidden();

AlreadyExecuted

Git Source

error AlreadyExecuted();

AlreadyFailed

Git Source

error AlreadyFailed();

DuplicatedSnapshotRoot

Git Source

error DuplicatedSnapshotRoot();

IncorrectMagicValue

Git Source

error IncorrectMagicValue();

GasLimitTooLow

Git Source

error GasLimitTooLow();

GasSuppliedTooLow

Git Source

error GasSuppliedTooLow();

ContentLengthTooBig

Git Source

error ContentLengthTooBig();

EthTransferFailed

Git Source

error EthTransferFailed();

InsufficientEthBalance

Git Source

error InsufficientEthBalance();

LocalGasDataNotSet

Git Source

error LocalGasDataNotSet();

RemoteGasDataNotSet

Git Source

error RemoteGasDataNotSet();

SummitTipTooHigh

Git Source

error SummitTipTooHigh();

TipsClaimMoreThanEarned

Git Source

error TipsClaimMoreThanEarned();

TipsClaimZero

Git Source

error TipsClaimZero();

TipsOverflow

Git Source

error TipsOverflow();

TipsValueTooLow

Git Source

error TipsValueTooLow();

IndexedTooMuch

Git Source

error IndexedTooMuch();

ViewOverrun

Git Source

error ViewOverrun();

OccupiedMemory

Git Source

error OccupiedMemory();

UnallocatedMemory

Git Source

error UnallocatedMemory();

PrecompileOutOfGas

Git Source

error PrecompileOutOfGas();

MulticallFailed

Git Source

error MulticallFailed();

SafeCall

Git Source

Library for performing safe calls to the recipients. Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall

Functions

safeCall

Performs a call to the recipient using the provided gas limit, msg.value and payload in a safe way:

  • If the recipient is not a contract, false is returned instead of reverting.
  • If the recipient call reverts for any reason, false is returned instead of reverting.
  • If the recipient call succeeds, true is returned, and any returned data is ignored.
function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)
    internal
    returns (bool success);

Parameters

NameTypeDescription
recipientaddressThe recipient of the call
gasLimituint256The gas limit to use for the call
msgValueuint256The msg.value to use for the call
payloadbytesThe payload to use for the call

Returns

NameTypeDescription
successboolTrue if the call succeeded, false otherwise

AgentFlag

Git Source

*Potential statuses for the off-chain bonded agent:

  • Unknown: never provided a bond => signature not valid
  • Active: has a bond in BondingManager => signature valid
  • Unstaking: has a bond in BondingManager, initiated the unstaking => signature not valid
  • Resting: used to have a bond in BondingManager, successfully unstaked => signature not valid
  • Fraudulent: proven to commit fraud, value in Merkle Tree not updated => signature not valid
  • Slashed: proven to commit fraud, value in Merkle Tree was updated => signature not valid Unstaked agent could later be added back to THE SAME domain by staking a bond again. Honest agent: Unknown -> Active -> unstaking -> Resting -> Active ... Malicious agent: Unknown -> Active -> Fraudulent -> Slashed Malicious agent: Unknown -> Active -> Unstaking -> Fraudulent -> Slashed*
enum AgentFlag {
    Unknown,
    Active,
    Unstaking,
    Resting,
    Fraudulent,
    Slashed
}

AgentStatus

Git Source

Struct for storing an agent in the BondingManager contract.

struct AgentStatus {
    AgentFlag flag;
    uint32 domain;
    uint32 index;
}

DisputeFlag

Git Source

Potential statuses of an agent in terms of being in dispute

  • None: agent is not in dispute
  • Pending: agent is in unresolved dispute
  • Slashed: agent was in dispute that lead to agent being slashed Note: agent who won the dispute has their status reset to None
enum DisputeFlag {
    None,
    Pending,
    Slashed
}

DisputeStatus

Git Source

Struct for storing dispute status of an agent.

struct DisputeStatus {
    DisputeFlag flag;
    uint40 openedAt;
    uint40 resolvedAt;
}

DestinationStatus

Git Source

Struct representing the status of Destination contract.

struct DestinationStatus {
    uint40 snapRootTime;
    uint40 agentRootTime;
    uint32 notaryIndex;
}

MessageStatus

Git Source

Potential statuses of the message in Execution Hub.

  • None: there hasn't been a valid attempt to execute the message yet
  • Failed: there was a valid attempt to execute the message, but recipient reverted
  • Success: there was a valid attempt to execute the message, and recipient did not revert Note: message can be executed until its status is Success
enum MessageStatus {
    None,
    Failed,
    Success
}

StructureUtils

Git Source

Functions

verifyActive

Checks that Agent is Active

function verifyActive(AgentStatus memory status) internal pure;

verifyUnstaking

Checks that Agent is Unstaking

function verifyUnstaking(AgentStatus memory status) internal pure;

verifyActiveUnstaking

Checks that Agent is Active or Unstaking

function verifyActiveUnstaking(AgentStatus memory status) internal pure;

verifyFraudulent

Checks that Agent is Fraudulent

function verifyFraudulent(AgentStatus memory status) internal pure;

verifyKnown

Checks that Agent is not Unknown

function verifyKnown(AgentStatus memory status) internal pure;

TypeCasts

Git Source

Functions

addressToBytes32

function addressToBytes32(address addr) internal pure returns (bytes32);

bytes32ToAddress

function bytes32ToAddress(bytes32 buf) internal pure returns (address);

Contents

AgentManager

Git Source

Inherits: MessagingBase, AgentManagerEvents, IAgentManager

AgentManager is used to keep track of all the bonded agents and their statuses. The exact logic of how the agent statuses are stored and updated is implemented in child contracts, and depends on whether the contract is used on Synapse Chain or on other chains. AgentManager is responsible for the following:

  • Keeping track of all the bonded agents and their statuses.
  • Keeping track of all the disputes between agents.
  • Notifying AgentSecured contracts about the opened and resolved disputes.
  • Notifying AgentSecured contracts about the slashed agents.

State Variables

origin

address public origin;

destination

address public destination;

inbox

address public inbox;

_agentDispute

mapping(uint256 => AgentDispute) internal _agentDispute;

_disputes

OpenedDispute[] internal _disputes;

__GAP

gap for upgrade safety

uint256[45] private __GAP;

Functions

onlyInbox

modifier onlyInbox();

onlyWhenStuck

modifier onlyWhenStuck();

__AgentManager_init

function __AgentManager_init(address origin_, address destination_, address inbox_) internal onlyInitializing;

openDispute

Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.

Will revert if any of these is true:

  • Caller is not Inbox.
  • Guard or Notary is already in Dispute.
function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyInbox;

Parameters

NameTypeDescription
guardIndexuint32Index of the Guard in the Agent Merkle Tree
notaryIndexuint32Index of the Notary in the Agent Merkle Tree

slashAgent

Allows Inbox to slash an agent, if their fraud was proven.

Will revert if any of these is true:

  • Caller is not Inbox.
  • Domain doesn't match the saved agent domain.
function slashAgent(uint32 domain, address agent, address prover) external onlyInbox;

Parameters

NameTypeDescription
domainuint32Domain where the Agent is active
agentaddressAddress of the Agent
proveraddressAddress that initially provided fraud proof

getAgent

Returns agent address and their current status for a given agent index.

Will return empty values if agent with given index doesn't exist.

function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);

Parameters

NameTypeDescription
indexuint256Agent index in the Agent Merkle Tree

Returns

NameTypeDescription
agentaddressAgent address
statusAgentStatusStatus for the given agent: (flag, domain, index)

agentStatus

Returns (flag, domain, index) for a given agent. See Structures.sol for details.

Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.

function agentStatus(address agent) public view returns (AgentStatus memory status);

Parameters

NameTypeDescription
agentaddressAgent address

Returns

NameTypeDescription
statusAgentStatusStatus for the given agent: (flag, domain, index).

getDisputesAmount

Returns the number of opened Disputes.

This includes the Disputes that have been resolved already.

function getDisputesAmount() external view returns (uint256);

getDispute

Returns information about the dispute with the given index.

Will revert if dispute with given index hasn't been opened yet.

function getDispute(uint256 index)
    external
    view
    returns (
        address guard,
        address notary,
        address slashedAgent,
        address fraudProver,
        bytes memory reportPayload,
        bytes memory reportSignature
    );

Parameters

NameTypeDescription
indexuint256Dispute index

Returns

NameTypeDescription
guardaddressAddress of the Guard in the Dispute
notaryaddressAddress of the Notary in the Dispute
slashedAgentaddressAddress of the Agent who was slashed when Dispute was resolved
fraudProveraddressAddress who provided fraud proof to resolve the Dispute
reportPayloadbytesRaw payload with report data that led to the Dispute
reportSignaturebytesGuard signature for the report payload

disputeStatus

Returns the current Dispute status of a given agent. See Structures.sol for details.

Every returned value will be set to zero if agent was not slashed and is not in Dispute. rival and disputePtr will be set to zero if the agent was slashed without being in Dispute.

function disputeStatus(address agent)
    external
    view
    returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);

Parameters

NameTypeDescription
agentaddressAgent address

Returns

NameTypeDescription
flagDisputeFlagFlag describing the current Dispute status for the agent: None/Pending/Slashed
rivaladdressAddress of the rival agent in the Dispute
fraudProveraddressAddress who provided fraud proof to resolve the Dispute
disputePtruint256Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.

_afterAgentSlashed

Hook that is called after agent was slashed in AgentManager and AgentSecured contracts were notified.

function _afterAgentSlashed(uint32 domain, address agent, address prover) internal virtual;

_notifyDisputeOpened

Child contract should implement the logic for notifying AgentSecured contracts about the opened dispute.

function _notifyDisputeOpened(uint32 guardIndex, uint32 notaryIndex) internal virtual;

_notifyDisputeResolved

Child contract should implement the logic for notifying AgentSecured contracts about the resolved dispute.

function _notifyDisputeResolved(uint32 slashedIndex, uint32 rivalIndex) internal virtual;

_slashAgent

Slashes the Agent and notifies the local Destination and Origin contracts about the slashed agent. Should be called when the agent fraud was confirmed.

function _slashAgent(uint32 domain, address agent, address prover) internal;

_resolveDispute

Resolves a Dispute between a slashed Agent and their Rival (if there was one).

function _resolveDispute(uint32 slashedIndex, address prover) internal;

_agentLeaf

Generates leaf to be saved in the Agent Merkle Tree

function _agentLeaf(AgentFlag flag, uint32 domain, address agent) internal pure returns (bytes32);

_storedAgentStatus

Returns the last known status for the agent from the Agent Merkle Tree. Note: the actual agent status (returned by agentStatus()) may differ, if agent fraud was proven.

function _storedAgentStatus(address agent) internal view virtual returns (AgentStatus memory);

_getAgent

Returns agent address for the given index. Returns zero for non existing indexes.

function _getAgent(uint256 index) internal view virtual returns (address);

_getIndex

Returns the index of the agent in the Agent Merkle Tree. Returns zero for non existing agents.

function _getIndex(address agent) internal view virtual returns (uint256);

Structs

AgentDispute

struct AgentDispute {
    DisputeFlag flag;
    uint88 disputePtr;
    address fraudProver;
}

OpenedDispute

struct OpenedDispute {
    uint32 guardIndex;
    uint32 notaryIndex;
    uint32 slashedIndex;
}

BondingManager

Git Source

Inherits: AgentManager, InterfaceBondingManager

BondingManager keeps track of all existing agents on the Synapse Chain. It utilizes a dynamic Merkle Tree to store the agent information. This enables passing only the latest merkle root of this tree (referenced as the Agent Merkle Root) to the remote chains, so that the agents could "register" themselves by proving their current status against this root. BondingManager is responsible for the following:

  • Keeping track of all existing agents, as well as their statuses. In the MVP version there is no token staking, which will be added in the future. Nonetheless, the agent statuses are still stored in the Merkle Tree, and the agent slashing is still possible, though with no reward/penalty for the reporter/reported.
  • Marking agents as "ready to be slashed" once their fraud is proven on the local or remote chain. Anyone could complete the slashing by providing the proof of the current agent status against the current Agent Merkle Root.
  • Sending Manager Message to remote LightManager to withdraw collected tips from the remote chain.
  • Accepting Manager Message from remote LightManager to slash agents on the Synapse Chain, when their fraud is proven on the remote chain.

State Variables

summit

address public summit;

_agentMap

mapping(address => AgentStatus) private _agentMap;

_domainAgents

mapping(uint32 => address[]) private _domainAgents;

_agents

address[] private _agents;

_agentTree

DynamicTree private _agentTree;

Functions

constructor

constructor(uint32 synapseDomain_) MessagingBase("0.0.3", synapseDomain_);

initialize

function initialize(address origin_, address destination_, address inbox_, address summit_) external initializer;

addAgent

Adds a new agent for the domain. This is either a fresh address (Inactive), or an agent who used to be active on the same domain before (Resting).

Inactive: proof should be the proof of inclusion of an empty leaf having index following the last added agent in the tree.

function addAgent(uint32 domain, address agent, bytes32[] memory proof) external onlyOwner;

Parameters

NameTypeDescription
domainuint32Domain where the Agent will be active
agentaddressAddress of the Agent
proofbytes32[]Merkle proof of the Inactive/Resting status for the agent

initiateUnstaking

Initiates the unstaking of the agent bond. Agent signature is immediately no longer considered valid on Synapse Chain, and will be invalid on other chains once the Light Manager updates their agent merkle root on these chains.

proof should be the proof of inclusion of the agent leaf with Active flag having index previously assigned to the agent.

function initiateUnstaking(uint32 domain, address agent, bytes32[] memory proof) external onlyOwner;

Parameters

NameTypeDescription
domainuint32Domain where the Agent is active
agentaddressAddress of the Agent
proofbytes32[]Merkle proof of the Active status for the agent

completeUnstaking

Completes the unstaking of the agent bond. Agent signature is no longer considered valid on any of the chains.

proof should be the proof of inclusion of the agent leaf with Unstaking flag having index previously assigned to the agent.

function completeUnstaking(uint32 domain, address agent, bytes32[] memory proof) external onlyOwner;

Parameters

NameTypeDescription
domainuint32Domain where the Agent was active
agentaddressAddress of the Agent
proofbytes32[]Merkle proof of the unstaking status for the agent

resolveDisputeWhenStuck

Allows contract owner to resolve a stuck Dispute. This could only be called if no fresh data has been submitted by the Notaries to the Inbox, which is required for the Dispute to be resolved naturally.

Will revert if any of these is true:

  • Caller is not contract owner.
  • Domain doesn't match the saved agent domain.
  • slashedAgent is not in Dispute.
  • Less than FRESH_DATA_TIMEOUT has passed since the last Notary submission to the Inbox.
function resolveDisputeWhenStuck(uint32 domain, address slashedAgent) external onlyOwner onlyWhenStuck;

Parameters

NameTypeDescription
domainuint32
slashedAgentaddressAgent that is being slashed

completeSlashing

Completes the slashing of the agent bond. Agent signature is no longer considered valid under the updated Agent Merkle Root.

proof should be the proof of inclusion of the agent leaf with Active/Unstaking flag having index previously assigned to the agent.

function completeSlashing(uint32 domain, address agent, bytes32[] memory proof) external;

Parameters

NameTypeDescription
domainuint32Domain where the Agent was active
agentaddressAddress of the Agent
proofbytes32[]Merkle proof of the active/unstaking status for the agent

remoteSlashAgent

Remote AgentManager should call this function to indicate that the agent has been proven to commit fraud on the origin chain.

This initiates the process of agent slashing. It could be immediately completed by anyone calling completeSlashing() providing a correct merkle proof for the OLD agent status. Note: as an extra security check this function returns its own selector, so that Destination could verify that a "remote" function was called when executing a manager message. Will revert if msgOrigin is equal to contract's local domain.

function remoteSlashAgent(uint32 msgOrigin, uint256 proofMaturity, uint32 domain, address agent, address prover)
    external
    returns (bytes4 magicValue);

Parameters

NameTypeDescription
msgOriginuint32
proofMaturityuint256
domainuint32Domain where the slashed agent was active
agentaddressAddress of the slashed Agent
proveraddressAddress that initially provided fraud proof to remote AgentManager

Returns

NameTypeDescription
magicValuebytes4Selector of this function

withdrawTips

Withdraws locked base message tips from requested domain Origin to the recipient. Issues a call to a local Origin contract, or sends a manager message to the remote chain.

Could only be called by the Summit contract.

function withdrawTips(address recipient, uint32 origin_, uint256 amount) external;

Parameters

NameTypeDescription
recipientaddressAddress to withdraw tips to
origin_uint32
amountuint256Tips value to withdraw

agentRoot

Returns the latest known root of the Agent Merkle Tree.

function agentRoot() external view override returns (bytes32);

getActiveAgents

Returns all active agents for a given domain.

function getActiveAgents(uint32 domain) external view returns (address[] memory agents);

Parameters

NameTypeDescription
domainuint32Domain to get agents from (ZERO for Guards)

agentLeaf

Returns a leaf representing the current status of agent in the Agent Merkle Tree.

Will return an empty leaf, if agent is not added to the tree yet.

function agentLeaf(address agent) external view returns (bytes32 leaf);

Parameters

NameTypeDescription
agentaddressAgent address

Returns

NameTypeDescription
leafbytes32Agent leaf in the Agent Merkle Tree

leafsAmount

Returns a total amount of leafs representing known agents.

This includes active, unstaking, resting and slashed agents. This also includes an empty leaf as the very first entry.

function leafsAmount() external view returns (uint256 amount);

getProof

Returns a proof of inclusion of the agent in the Agent Merkle Tree.

Will return a proof for an empty leaf, if agent is not added to the tree yet. This proof could be used by ANY next new agent that calls {addAgent}.

function getProof(address agent) external view returns (bytes32[] memory proof);

Parameters

NameTypeDescription
agentaddressAgent address

Returns

NameTypeDescription
proofbytes32[]Merkle proof for the agent

allLeafs

Returns a full list of leafs from the Agent Merkle Tree.

This might consume a lot of gas, do not use this on-chain.

function allLeafs() public view returns (bytes32[] memory leafs);

getLeafs

Returns a list of leafs from the Agent Merkle Tree with indexes [indexFrom .. indexFrom + amount).

This might consume a lot of gas, do not use this on-chain.

function getLeafs(uint256 indexFrom, uint256 amount) public view returns (bytes32[] memory leafs);

_updateLeaf

Updates value in the Agent Merkle Tree to reflect the newStatus. Will revert, if supplied proof for the old value is incorrect.

function _updateLeaf(bytes32 oldValue, bytes32[] memory proof, AgentStatus memory newStatus, address agent) internal;

_notifyDisputeOpened

Notify local AgentSecured contracts about the opened dispute.

function _notifyDisputeOpened(uint32 guardIndex, uint32 notaryIndex) internal override;

_notifyDisputeResolved

Notify local AgentSecured contracts about the resolved dispute.

function _notifyDisputeResolved(uint32 slashedIndex, uint32 rivalIndex) internal override;

_storedAgentStatus

Returns the status of the agent.

function _storedAgentStatus(address agent) internal view override returns (AgentStatus memory);

_getAgent

Returns agent address for the given index. Returns zero for non existing indexes.

function _getAgent(uint256 index) internal view override returns (address agent);

_getIndex

Returns the index of the agent in the Agent Merkle Tree. Returns zero for non existing agents.

function _getIndex(address agent) internal view override returns (uint256 index);

_getLeaf

Returns the current leaf representing agent in the Agent Merkle Tree.

function _getLeaf(address agent) internal view returns (bytes32 leaf);

_getLeaf

Returns a leaf from the Agent Merkle Tree with a given index.

function _getLeaf(uint256 index) internal view returns (bytes32 leaf);

LightManager

Git Source

Inherits: AgentManager, InterfaceLightManager

LightManager keeps track of all agents on chains other than Synapse Chain. Is uses the Agent Merkle Roots from the Notary-signed attestations to stay in sync with the BondingManager. LightManager is responsible for the following:

  • Accepting the Agent Merkle Roots (passing the optimistic period check) from the Destination contract.
  • Using these roots to enable agents to register themselves by proving their status.
  • Accepting Manager Message from BondingManager on Synapse Chain to withdraw tips.
  • Sending Manager Messages to BondingManager on Synapse Chain to slash agents, when their fraud is proven.

State Variables

agentRoot

Returns the latest known root of the Agent Merkle Tree.

bytes32 public agentRoot;

_proposedAgentRoot

Pending Agent Merkle Root that was proposed by the contract owner.

bytes32 internal _proposedAgentRoot;

_agentRootProposedAt

Timestamp when the Agent Merkle Root was proposed by the contract owner.

uint256 internal _agentRootProposedAt;

_agentMap

mapping(bytes32 => mapping(address => AgentStatus)) private _agentMap;

_agents

mapping(uint256 => address) private _agents;

_agentIndexes

mapping(address => uint256) private _agentIndexes;

Functions

constructor

constructor(uint32 synapseDomain_) MessagingBase("0.0.3", synapseDomain_);

initialize

function initialize(address origin_, address destination_, address inbox_) external initializer;

proposeAgentRootWhenStuck

Allows contract owner to set the agent root to resolve the "stuck" chain by proposing the new agent root. The contract owner will be able to resolve the proposed agent root after a certain period of time. Note: this function could be called multiple times, each time the timer will be reset. This could only be called if no fresh data has been submitted by the Notaries to the Inbox, indicating that the chain is stuck for one of the reasons:

  • All active Notaries are in Dispute.
  • No active Notaries exist under the current agent root.

*Will revert if any of the following conditions is met:

  • Caller is not the contract owner.
  • Agent root is empty.
  • The chain is not in a stuck state (has recently received a fresh data from the Notaries).*
function proposeAgentRootWhenStuck(bytes32 agentRoot_) external onlyOwner onlyWhenStuck;

Parameters

NameTypeDescription
agentRoot_bytes32New Agent Merkle Root that is proposed to be set

cancelProposedAgentRoot

Allows contract owner to cancel the previously proposed agent root.

*Will revert if any of the following conditions is met:

  • Caller is not the contract owner.
  • No agent root was proposed.*
function cancelProposedAgentRoot() external onlyOwner;

resolveProposedAgentRoot

Allows contract owner to resolve the previously proposed agent root. This will update the agent root, allowing the agents to update their status, effectively resolving the "stuck" chain.

Should proceed with the proposed root, even if new Notary data is available. This is done to prevent rogue Notaries from going offline and then indefinitely blocking the agent root resolution, thus onlyWhenStuck modifier is not used here.

function resolveProposedAgentRoot() external onlyOwner;

updateAgentStatus

Updates agent status, using a proof against the latest known Agent Merkle Root.

Will revert if the provided proof doesn't match the latest merkle root.

function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;

Parameters

NameTypeDescription
agentaddressAgent address
statusAgentStatusStructure specifying agent status: (flag, domain, index)
proofbytes32[]Merkle proof of Active status for the agent

setAgentRoot

Updates the root of Agent Merkle Tree that the Light Manager is tracking. Could be only called by a local Destination contract, which is supposed to verify the attested Agent Merkle Roots.

function setAgentRoot(bytes32 agentRoot_) external;

Parameters

NameTypeDescription
agentRoot_bytes32New Agent Merkle Root

remoteWithdrawTips

Withdraws locked base message tips from local Origin to the recipient.

Could only be remote-called by BondingManager contract on Synapse Chain. Note: as an extra security check this function returns its own selector, so that Destination could verify that a "remote" function was called when executing a manager message.

function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)
    external
    returns (bytes4 magicValue);

Parameters

NameTypeDescription
msgOriginuint32
proofMaturityuint256
recipientaddressAddress to withdraw tips to
amountuint256Tips value to withdraw

proposedAgentRootData

Returns the latest proposed agent root and the timestamp when it was proposed.

Will return zero values if no agent root was proposed, or if the proposed agent root was already resolved.

function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);

_afterAgentSlashed

function _afterAgentSlashed(uint32 domain, address agent, address prover) internal virtual override;

_notifyDisputeOpened

Notify local AgentSecured contracts about the opened dispute.

function _notifyDisputeOpened(uint32 guardIndex, uint32 notaryIndex) internal override;

_notifyDisputeResolved

Notify local AgentSecured contracts about the resolved dispute.

function _notifyDisputeResolved(uint32 slashedIndex, uint32 rivalIndex) internal override;

_setAgentRoot

Updates the Agent Merkle Root that Light Manager is tracking.

function _setAgentRoot(bytes32 _agentRoot) internal;

_storedAgentStatus

Returns the stored status for the agent: whether or not they have been added using latest Agent merkle Root.

function _storedAgentStatus(address agent) internal view override returns (AgentStatus memory);

_getAgent

Returns agent address for the given index. Returns zero for non existing indexes, or for indexes of the agents that have not been added to Light Manager yet.

function _getAgent(uint256 index) internal view override returns (address agent);

_getIndex

Returns the index of the agent in the Agent Merkle Tree. Returns zero for non existing agents, or for agents that have not been added to Light Manager yet.

function _getIndex(address agent) internal view override returns (uint256 index);

Destination

Git Source

Inherits: ExecutionHub, DestinationEvents, InterfaceDestination

Destination contract is used for receiving messages from other chains. It relies on Notary-signed statements to get the truthful states of the remote chains. These states are then used to verify the validity of the messages sent from the remote chains. Destination is responsible for the following:

  • Accepting the Attestations from the local Inbox contract.
  • Using these Attestations to execute the messages (see parent ExecutionHub).
  • Passing the Agent Merkle Roots from the Attestations to the local LightManager contract, if deployed on a non-Synapse chain.
  • Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed by the local GasOracle contract.

State Variables

_nextAgentRoot

Invariant: this is either current LightManager root, or the pending root to be passed to LightManager once its optimistic period is over.

bytes32 internal _nextAgentRoot;

destStatus

Returns status of Destination contract as far as snapshot/agent roots are concerned

DestinationStatus public destStatus;

lastAttestationNonce

Returns the nonce of the last attestation submitted by a Notary with a given agent index.

Will return zero if the Notary hasn't submitted any attestations yet.

mapping(uint32 => uint32) public lastAttestationNonce;

_storedAttestations

Stored lookup data for all accepted Notary Attestations

StoredAttData[] internal _storedAttestations;

_storedGasData

Remote domains GasData submitted by Notaries

mapping(uint32 => StoredGasData) internal _storedGasData;

Functions

constructor

constructor(uint32 synapseDomain_, address agentManager_, address inbox_)
    AgentSecured("0.0.3", synapseDomain_, agentManager_, inbox_);

initialize

Initializes Destination contract:

  • msg.sender is set as contract owner
function initialize(bytes32 agentRoot) external initializer;

acceptAttestation

Accepts an attestation, which local AgentManager verified to have been signed by an active Notary for this chain.

Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.

  • Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.
  • Messages coming from chains included in the Attestation's snapshot could be proven.
  • Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.

Will revert if any of these is true:

  • Called by anyone other than local AgentManager.
  • Attestation payload is not properly formatted.
  • Attestation signer is in Dispute.
  • Attestation's snapshot root has been previously submitted. Note: agentRoot and snapGas have been verified by the local AgentManager.
function acceptAttestation(
    uint32 notaryIndex,
    uint256 sigIndex,
    bytes memory attPayload,
    bytes32 agentRoot,
    ChainGas[] memory snapGas
) external onlyInbox returns (bool wasAccepted);

Parameters

NameTypeDescription
notaryIndexuint32Index of Attestation Notary in Agent Merkle Tree
sigIndexuint256Index of stored Notary signature
attPayloadbytesRaw payload with Attestation data
agentRootbytes32Agent Merkle Root from the Attestation
snapGasChainGas[]Gas data for each chain in the Attestation's snapshot

Returns

NameTypeDescription
wasAcceptedboolWhether the Attestation was accepted

passAgentRoot

Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.

Will do nothing, if root optimistic period is not over.

function passAgentRoot() public returns (bool rootPending);

Returns

NameTypeDescription
rootPendingboolWhether there is a pending agent merkle root left

attestationsAmount

Returns the total amount of Notaries attestations that have been accepted.

function attestationsAmount() external view returns (uint256);

getAttestation

Returns a Notary-signed attestation with a given index.

Index refers to the list of all attestations accepted by this contract.

Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit. Will return an empty signature if this contract is deployed on Synapse Chain.

function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);

Parameters

NameTypeDescription
indexuint256Attestation index

Returns

NameTypeDescription
attPayloadbytesRaw payload with Attestation data
attSignaturebytesNotary signature for the reported attestation

getGasData

Returns the gas data for a given chain from the latest accepted attestation with that chain.

Will return empty values if there is no data for the domain, or if the notary who provided the data is in dispute.

function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);

Parameters

NameTypeDescription
domainuint32Domain for the chain

Returns

NameTypeDescription
gasDataGasDataGas data for the chain
dataMaturityuint256Gas data age in seconds

nextAgentRoot

Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.

function nextAgentRoot() external view returns (bytes32);

_saveAgentRoot

Saves Agent Merkle Root from the accepted attestation, if there is no pending root to be passed to LightManager. Returns the updated "last snapshot root / last agent root" status struct.

function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)
    internal
    returns (DestinationStatus memory status);

_saveGasData

Saves updated values from the snapshot's gas data list.

function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal;

Structs

StoredAttData

struct StoredAttData {
    bytes32 agentRoot;
    bytes32 dataHash;
}

StoredGasData

struct StoredGasData {
    GasData gasData;
    uint32 notaryIndex;
    uint40 submittedAt;
}

GasOracle

Git Source

Inherits: MessagingBase, GasOracleEvents, InterfaceGasOracle

GasOracle contract is responsible for tracking the gas data for both local and remote chains.

Local gas data tracking

  • GasOracle is using the available tools such as tx.gasprice to track the time-averaged values for different "gas statistics" (to be implemented in the future).
  • These values are cached, so that the reported values are only changed when a big enough change is detected.
  • In the MVP version the gas data is set manually by the owner of the contract.
  • The reported values are included in Origin's State, whenever a new message is sent.

This leads to cached "chain gas data" being included in the Guard and Notary snapshots.

Remote gas data tracking

  • To track gas data for the remote chains, GasOracle relies on the Notaries to pass the gas data alongside their attestations.
  • As the gas data is cached, this leads to a storage write only when the gas data for the remote chain changes significantly.
  • GasOracle is in charge of enforcing the optimistic periods for the gas data it gets from Destination.
  • The optimistic period is smaller when the "gas statistics" are increasing, and bigger when they are decreasing.

Reason for that is that the decrease of the gas price leads to lower execution/delivery tips, and we want the Executors to be protected against that.

State Variables

destination

address public immutable destination;

GAS_DATA_INCREASED_OPTIMISTIC_PERIOD

uint256 public constant GAS_DATA_INCREASED_OPTIMISTIC_PERIOD = 5 minutes;

GAS_DATA_DECREASED_OPTIMISTIC_PERIOD

uint256 public constant GAS_DATA_DECREASED_OPTIMISTIC_PERIOD = 1 hours;

_gasData

mapping(uint32 => GasData) internal _gasData;

summitTipWei

uint256 public summitTipWei;

Functions

constructor

constructor(uint32 synapseDomain_, address destination_) MessagingBase("0.0.3", synapseDomain_);

initialize

Initializes GasOracle contract:

  • msg.sender is set as contract owner
function initialize() external initializer;

setGasData

MVP function to set the gas data for the given domain.

function setGasData(
    uint32 domain,
    uint256 gasPrice,
    uint256 dataPrice,
    uint256 execBuffer,
    uint256 amortAttCost,
    uint256 etherPrice,
    uint256 markup
) external onlyOwner;

setSummitTip

MVP function to set the summit tip.

function setSummitTip(uint256 summitTipWei_) external onlyOwner;

updateGasData

Fetches the latest gas data for the chain from Destination contract, and uses it to update the oracle values for the requested chain.

function updateGasData(uint32 domain) external;

Parameters

NameTypeDescription
domainuint32Domain to update the gas data for

getDecodedGasData

Returns the gas data for the given domain, in the decoded format.

function getDecodedGasData(uint32 domain)
    external
    view
    returns (
        uint256 gasPrice,
        uint256 dataPrice,
        uint256 execBuffer,
        uint256 amortAttCost,
        uint256 etherPrice,
        uint256 markup
    );

Parameters

NameTypeDescription
domainuint32Domain of chain to get gas data for

Returns

NameTypeDescription
gasPriceuint256Gas price for the chain (in Wei per gas unit)
dataPriceuint256Calldata price (in Wei per byte of content)
execBufferuint256Tx fee safety buffer for message execution (in Wei)
amortAttCostuint256Amortized cost for attestation submission (in Wei)
etherPriceuint256Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)
markupuint256Markup for the message execution (in BWAD)

getGasData

Returns the gas data for the local chain.

function getGasData() external view returns (uint256 paddedGasData);

getMinimumTips

Returns the minimum tips for sending a message to a given destination.

function getMinimumTips(uint32 destination_, uint256 paddedRequest, uint256 contentLength)
    external
    view
    returns (uint256 paddedTips);

Parameters

NameTypeDescription
destination_uint32
paddedRequestuint256Padded encoded message execution request on destination chain
contentLengthuint256The length of the message content

Returns

NameTypeDescription
paddedTipsuint256Padded encoded minimum tips information

_setGasData

Sets the gas data for the given domain, and emits a corresponding event.

function _setGasData(uint32 domain, GasData updatedGasData) internal;

_fetchGasData

Returns the updated gas data for the given domain by optimistically consuming the data from the Destination contract.

function _fetchGasData(uint32 domain) internal view returns (bool wasUpdated, GasData updatedGasData);

_updateGasParameter

Returns the updated value for the gas parameter, given the maturity of the incoming data.

function _updateGasParameter(Number current, Number incoming, uint256 dataMaturity)
    internal
    pure
    returns (Number updatedParameter);

Origin

Git Source

Inherits: StateHub, OriginEvents, InterfaceOrigin

Origin contract is used for sending messages to remote chains. It is done by inserting the message hashes into the Origin Merkle, which makes it possible to prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain. Origin is responsible for the following:

  • Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.
  • Keeping track of its own historical states (see parent contract StateHub).
  • Enforcing minimum tip values for sent base messages based on the provided execution requests.
  • Distributing the collected tips upon request from a local AgentManager contract.

State Variables

gasOracle

address public immutable gasOracle;

Functions

onlyRemoteDestination

modifier onlyRemoteDestination(uint32 destination);

constructor

constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)
    AgentSecured("0.0.3", synapseDomain_, agentManager_, inbox_);

initialize

Initializes Origin contract:

  • msg.sender is set as contract owner
  • State of "empty merkle tree" is saved
function initialize() external initializer;

sendBaseMessage

Send a message to the recipient located on destination domain.

*Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered. Will revert if any of these is true:

  • destination is equal to contract's local domain
  • content length is greater than MAX_CONTENT_BYTES
  • msg.value is lower than value of minimum tips for the given message*
function sendBaseMessage(
    uint32 destination,
    bytes32 recipient,
    uint32 optimisticPeriod,
    uint256 paddedRequest,
    bytes memory content
) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash);

Parameters

NameTypeDescription
destinationuint32Domain of destination chain
recipientbytes32Address of recipient on destination chain as bytes32
optimisticPerioduint32Optimistic period for message execution on destination chain
paddedRequestuint256Padded encoded message execution request on destination chain
contentbytesRaw bytes content of message

Returns

NameTypeDescription
messageNonceuint32Nonce of the sent message
messageHashbytes32Hash of the sent message

sendManagerMessage

Send a manager message to the destination domain.

This could only be called by AgentManager, which takes care of encoding the calldata payload. Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain so that the AgentManager could verify where the Manager Message came from and how mature is the proof. Note: function is not payable, as no tips are required for sending a manager message. Will revert if destination is equal to contract's local domain.

function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)
    external
    onlyAgentManager
    onlyRemoteDestination(destination)
    returns (uint32 messageNonce, bytes32 messageHash);

Parameters

NameTypeDescription
destinationuint32Domain of destination chain
optimisticPerioduint32Optimistic period for message execution on destination chain
payloadbytesPayload for calling AgentManager on destination chain (with extra security args)

withdrawTips

Withdraws locked base message tips to the recipient.

Could only be called by a local AgentManager.

function withdrawTips(address recipient, uint256 amount) external onlyAgentManager;

Parameters

NameTypeDescription
recipientaddressAddress to withdraw tips to
amountuint256Tips value to withdraw

getMinimumTipsValue

Returns the minimum tips value for sending a message to a given destination.

Using at least tipsValue as msg.value for sendBaseMessage() will guarantee that the message will be accepted.

function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)
    external
    view
    returns (uint256 tipsValue);

Parameters

NameTypeDescription
destinationuint32Domain of destination chain
paddedRequestuint256Padded encoded message execution request on destination chain
contentLengthuint256The length of the message content

Returns

NameTypeDescription
tipsValueuint256Minimum tips value for a message to be accepted

_sendMessage

Sends the given message to the specified destination. Message hash is inserted into the Origin Merkle Tree, which will enable message execution on destination chain.

function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)
    internal
    returns (uint32 messageNonce, bytes32 messageHash);

_getMinimumTips

Returns the minimum tips for sending a message to the given destination with the given request and content.

function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)
    internal
    view
    returns (Tips);

_fetchGasData

Gets the current gas data from the gas oracle to be saved as part of the Origin State.

function _fetchGasData() internal view override returns (GasData);

Summit

Git Source

Inherits: SnapshotHub, SummitEvents, InterfaceSummit

Summit contract is the cornerstone of the Synapse messaging protocol. This is where the states of all the remote chains (provided collectively by the Guards and Notaries) are stored. This is also the place where the tips are distributed among the off-chain actors. Summit is responsible for the following:

  • Accepting Guard and Notary snapshots from the local Inbox contract, and storing the states from these snapshots (see parent contract SnapshotHub).
  • Accepting Notary Receipts from the local Inbox contract, and using them to distribute tips among the off-chain actors that participated in the message lifecycle.

State Variables

_receipts

mapping(bytes32 => SummitReceipt) private _receipts;

_receiptStatus

mapping(bytes32 => ReceiptStatus) private _receiptStatus;

_receiptTips

mapping(bytes32 => ReceiptTips) private _receiptTips;

_receiptQueue

DoubleEndedQueue.Bytes32Deque private _receiptQueue;

actorTips

Returns earned and claimed tips for the actor. Note: Tips for address(0) belong to the Treasury.

mapping(address => mapping(uint32 => ActorTips)) public actorTips;

Functions

constructor

constructor(uint32 synapseDomain_, address agentManager_, address inbox_)
    AgentSecured("0.0.3", synapseDomain_, agentManager_, inbox_);

initialize

function initialize() external initializer;

acceptReceipt

Accepts a receipt, which local AgentManager verified to have been signed by an active Notary.

Receipt is a statement about message execution status on the remote chain.

  • This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.
  • Notary who signed the receipt is referenced as the "Receipt Notary".
  • Notary who signed the attestation on destination chain is referenced as the "Attestation Notary".

Will revert if any of these is true:

  • Called by anyone other than local AgentManager.
  • Receipt body payload is not properly formatted.
  • Receipt signer is in Dispute.
  • Receipt's snapshot root is unknown.
function acceptReceipt(
    uint32 rcptNotaryIndex,
    uint32 attNotaryIndex,
    uint256 sigIndex,
    uint32 attNonce,
    uint256 paddedTips,
    bytes memory rcptPayload
) external onlyInbox returns (bool wasAccepted);

Parameters

NameTypeDescription
rcptNotaryIndexuint32Index of Receipt Notary in Agent Merkle Tree
attNotaryIndexuint32Index of Attestation Notary in Agent Merkle Tree
sigIndexuint256Index of stored Notary signature
attNonceuint32Nonce of the attestation used for proving the executed message
paddedTipsuint256Padded encoded paid tips information
rcptPayloadbytesRaw payload with message execution receipt

Returns

NameTypeDescription
wasAcceptedboolWhether the receipt was accepted

acceptGuardSnapshot

Accepts a snapshot, which local AgentManager verified to have been signed by an active Guard.

Snapshot is a list of states for a set of Origin contracts residing on any of the chains. All the states in the Guard-signed snapshot become available for Notary signing. Will revert if any of these is true:

  • Called by anyone other than local AgentManager.
  • Snapshot payload is not properly formatted.
  • Snapshot contains a state older then the Guard has previously submitted.
function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external onlyInbox;

Parameters

NameTypeDescription
guardIndexuint32Index of Guard in Agent Merkle Tree
sigIndexuint256Index of stored Agent signature
snapPayloadbytesRaw payload with snapshot data

acceptNotarySnapshot

Accepts a snapshot, which local AgentManager verified to have been signed by an active Notary.

Snapshot is a list of states for a set of Origin contracts residing on any of the chains. Snapshot Merkle Root is calculated and saved for valid snapshots, i.e. snapshots which are only using states previously submitted by any of the Guards.

  • Notary could use states singed by the same of different Guards in their snapshot.
  • Notary could then proceed to sign the attestation for their submitted snapshot.

Will revert if any of these is true:

  • Called by anyone other than local AgentManager.
  • Snapshot payload is not properly formatted.
  • Snapshot contains a state older then the Notary has previously submitted.
  • Snapshot contains a state that no Guard has previously submitted.
function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)
    external
    onlyInbox
    returns (bytes memory attPayload);

Parameters

NameTypeDescription
notaryIndexuint32Index of Notary in Agent Merkle Tree
sigIndexuint256Index of stored Agent signature
agentRootbytes32Current root of the Agent Merkle Tree
snapPayloadbytesRaw payload with snapshot data

Returns

NameTypeDescription
attPayloadbytesRaw payload with data for attestation derived from Notary snapshot.

distributeTips

Distributes tips using the first Receipt from the "receipt quarantine queue". Possible scenarios:

  • Receipt queue is empty => does nothing
  • Receipt optimistic period is not over => does nothing
  • Either of Notaries present in Receipt was slashed => receipt is deleted from the queue
  • Either of Notaries present in Receipt in Dispute => receipt is moved to the end of queue
  • None of the above => receipt tips are distributed

Returned value makes it possible to do the following: while (distributeTips()) {}

function distributeTips() public returns (bool queuePopped);

Returns

NameTypeDescription
queuePoppedboolWhether the first element was popped from the queue

withdrawTips

Withdraws locked base message tips from requested domain Origin to the recipient. This is done by a call to a local Origin contract, or by a manager message to the remote chain.

This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.

function withdrawTips(uint32 origin, uint256 amount) external;

Parameters

NameTypeDescription
originuint32Domain of chain to withdraw tips on
amountuint256Amount of tips to withdraw

receiptQueueLength

Returns the amount of receipts in the "Receipt Quarantine Queue".

function receiptQueueLength() external view returns (uint256);

getLatestState

Returns the state with the highest known nonce submitted by any of the currently active Guards.

function getLatestState(uint32 origin) external view returns (bytes memory statePayload);

Parameters

NameTypeDescription
originuint32Domain of origin chain

Returns

NameTypeDescription
statePayloadbytesRaw payload with latest active Guard state for origin

_checkNotaryDisputed

*Checks if the given Notary has been disputed.

  • Notary was slashed => receipt is invalided and deleted
  • Notary is in Dispute => receipt handling is postponed*
function _checkNotaryDisputed(bytes32 messageHash, uint32 notaryIndex) internal returns (bool queuePopped);

_deleteFromQueue

Deletes all stored receipt data and removes it from the queue.

function _deleteFromQueue(bytes32 messageHash) internal;

_moveToBack

Moves the front element of the queue to its back.

function _moveToBack() internal;

_saveReceipt

Saves the message from the receipt into the "quarantine queue". Once message leaves the queue, tips associated with the message are distributed across off-chain actors.

function _saveReceipt(
    Receipt rcpt,
    Tips tips,
    uint32 rcptNotaryIndex,
    uint32 attNotaryIndex,
    uint256 sigIndex,
    uint32 attNonce
) internal returns (bool);

_awardTips

Awards tips to the agent/actors that participated in message lifecycle

function _awardTips(
    uint32 rcptNotaryIndex,
    uint32 attNotaryIndex,
    bytes32 messageHash,
    SummitReceipt memory summitRcpt,
    ReceiptStatus memory rcptStatus
) internal;

_awardAgentTip

Award tip to the bonded agent

function _awardAgentTip(uint32 agentIndex, uint32 origin, uint64 tip) internal;

_awardActorTip

Award tip to any actor whether bonded or unbonded

function _awardActorTip(address actor, uint32 origin, uint64 tip) internal;

_awardReceiptTip

Award tip for posting Receipt to Summit contract.

function _awardReceiptTip(uint32 rcptNotaryIndex, bool awardFirst, bool awardFinal, uint32 origin, uint64 summitTip)
    internal;

_awardSnapshotTip

Award tip for posting Snapshot to Summit contract.

function _awardSnapshotTip(uint32 attNonce, uint8 stateIndex, uint32 origin, uint64 summitTip) internal;

_snapshotTip

Returns "snapshot part" of the summit tip.

function _snapshotTip(uint64 summitTip) internal pure returns (uint64);

_receiptTip

Returns "receipt part" of the summit tip.

function _receiptTip(uint64 summitTip) internal pure returns (uint64);

Structs

SummitReceipt

struct SummitReceipt {
    uint32 origin;
    uint32 destination;
    uint32 attNonce;
    uint8 stateIndex;
    uint32 attNotaryIndex;
    address firstExecutor;
    address finalExecutor;
}

ReceiptStatus

struct ReceiptStatus {
    MessageStatus status;
    bool pending;
    bool tipsAwarded;
    uint32 receiptNotaryIndex;
    uint40 submittedAt;
}

ReceiptTips

struct ReceiptTips {
    uint64 summitTip;
    uint64 attestationTip;
    uint64 executionTip;
    uint64 deliveryTip;
}

ActorTips

Struct for storing the actor tips for a given origin domain.

struct ActorTips {
    uint128 earned;
    uint128 claimed;
}