Skip to main content
Version: Endpoint V1 Docs

StoredPayload

If a message arrives at the destination and reverts or runs out of gas during execution it is saved on the destination side. Anyone can go to the destination chain and pay for the transaction to be retried, however if there is a logical error it may need to be force ejected. StoredPayloads will block the nonce-ordered flow of messages.

You can check for a StoredPayload using the Endpoint.sol's hasStoredPayload function, supplying the source chainId and source User Application address (which is in the TrustedRemote 40byte format).

Check for StoredPayload

// Endpoint.sol check for StoredPayload
function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view override returns (bool) {
StoredPayload storage sp = storedPayload[_srcChainId][_srcAddress];
return sp.payloadHash != bytes32(0);
}

To clear a StoredPayload, call retryPayload on the message that was stored, on the destination chain. You should call this function on the Endpoint.

// Endpoint.sol
function retryPayload(
uint16 _srcChainId,
bytes calldata _srcAddress,
bytes calldata _payload
) external override receiveNonReentrant { ... }

Note: most block explorers will show the payload parameter in the Logs tab, which could make it easy to find in the case you need to call retryPayload to unblock the queue.

Also, you may implement your UA as the NonblockingLzApp which is an option offered that allows messages to flow regardless of error (which will all be stored on the destination to be dealt with anytime)

Force eject the StoredPayload, unblocking the queue by DESTROYING (see: be very careful) the transaction forever. This is a very powerful function, and only the User Application onlyOwner can perform it.

// Endpoint.sol
function forceResumeReceive(
uint16 _srcChainId,
bytes calldata _srcAddress
) external override onlyOwner {

Fix a Stored Payload

Go here for information on fixing a StoredPayload