Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions contracts/base/AppGatewayBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -344,13 +344,6 @@ abstract contract AppGatewayBase is AddressResolverUtil, IAppGateway, FeesPlugin
}
}

function callFromChain(
uint32 chainSlug_,
address plug_,
bytes32 params_,
bytes calldata payload_
) external virtual onlyWatcherPrecompile {}

/// @notice Initializes the contract
/// @param chainSlug_ The chain slug
function initialize(uint32 chainSlug_) public virtual {}
Expand Down
7 changes: 5 additions & 2 deletions contracts/base/PlugBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ abstract contract PlugBase is IPlug {
ISocket public socket__;
address public appGateway;
uint256 public isSocketInitialized;
bytes public overrides;

error SocketAlreadyInitialized();
event ConnectorPlugDisconnected();
Expand Down Expand Up @@ -52,8 +53,10 @@ abstract contract PlugBase is IPlug {
socket__ = ISocket(socket_);
}

function _callAppGateway(bytes memory payload_, bytes32 params_) internal returns (bytes32) {
return socket__.callAppGateway(payload_, params_);
/// @notice Sets the overrides needed for the trigger
/// @param overrides_ The overrides
function _setOverrides(bytes memory overrides_) internal {
overrides = overrides_;
}

function initSocket(
Expand Down
7 changes: 0 additions & 7 deletions contracts/interfaces/IAppGateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,6 @@ interface IAppGateway {

function onRequestComplete(uint40 requestCount_, bytes calldata onCompleteData_) external;

function callFromChain(
uint32 chainSlug_,
address plug_,
bytes32 params_,
bytes calldata payload_
) external;

function handleRevert(uint40 requestCount_, bytes32 payloadId_) external;

/// @notice initialize the contracts on chain
Expand Down
2 changes: 2 additions & 0 deletions contracts/interfaces/IPlug.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ pragma solidity ^0.8.21;
*/
interface IPlug {
function initSocket(address appGateway_, address socket_, address switchboard_) external;

function overrides() external view returns (bytes memory);
}
21 changes: 5 additions & 16 deletions contracts/interfaces/ISocket.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity ^0.8.21;

import {ExecuteParams} from "../protocol/utils/common/Structs.sol";

/**
* @title ISocket
* @notice An interface for a Chain Abstraction contract
Expand Down Expand Up @@ -33,32 +34,20 @@ interface ISocket {

/**
* @notice emits the message details when a new message arrives at outbound
* @param callId call id
* @param triggerId call id
* @param chainSlug local chain slug
* @param plug local plug address
* @param appGateway appGateway address to trigger the call
* @param params params, for specifying details like fee pool chain, fee pool token and max fees if required
* @param overrides params, for specifying details like fee pool chain, fee pool token and max fees if required
* @param payload the data which will be used by contracts on chain
*/
event AppGatewayCallRequested(
bytes32 callId,
bytes32 triggerId,
uint32 chainSlug,
address plug,
address appGateway,
bytes32 params,
bytes overrides,
bytes payload
);

/**
* @notice To call the appGateway on EVMx. Should only be called by a plug.
* @param payload_ bytes to be delivered to the Plug on EVMx
* @param params_ a 32 bytes param to add details for execution.
*/
function callAppGateway(
bytes calldata payload_,
bytes32 params_
) external returns (bytes32 callId);

/**
* @notice executes a payload
*/
Expand Down
15 changes: 5 additions & 10 deletions contracts/interfaces/IWatcherPrecompile.sol
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.21;

import {DigestParams, ResolvedPromises, PayloadParams, CallFromChainParams, PayloadSubmitParams, RequestParams} from "../protocol/utils/common/Structs.sol";
import {DigestParams, ResolvedPromises, PayloadParams, TriggerParams, PayloadSubmitParams, RequestParams} from "../protocol/utils/common/Structs.sol";
import {IWatcherPrecompileLimits} from "./IWatcherPrecompileLimits.sol";
import {IWatcherPrecompileConfig} from "./IWatcherPrecompileConfig.sol";

/// @title IWatcherPrecompile
/// @notice Interface for the Watcher Precompile system that handles payload verification and execution
/// @dev Defines core functionality for payload processing and promise resolution
interface IWatcherPrecompile {
event CalledAppGateway(
bytes32 callId,
uint32 chainSlug,
address plug,
address appGateway,
bytes32 params,
bytes payload
);
event CalledAppGateway(bytes32 triggerId);

event AppGatewayCallFailed(bytes32 triggerId);

/// @notice Emitted when a new query is requested
event QueryRequested(PayloadParams params);
Expand Down Expand Up @@ -146,7 +141,7 @@ interface IWatcherPrecompile {
function setMaxTimeoutDelayInSeconds(uint256 maxTimeoutDelayInSeconds_) external;

function callAppGateways(
CallFromChainParams[] calldata params_,
TriggerParams[] calldata params_,
uint256 signatureNonce_,
bytes calldata signature_
) external;
Expand Down
1 change: 1 addition & 0 deletions contracts/interfaces/IWatcherPrecompileConfig.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ interface IWatcherPrecompileConfig {
function setSwitchboard(uint32 chainSlug_, bytes32 sbType_, address switchboard_) external;

/// @notice Sets valid plugs for each chain slug
/// @dev This function is used to verify if a plug deployed on a chain slug is valid connection to the app gateway
function setIsValidPlug(uint32 chainSlug_, address plug_, bool isValid_) external;

/// @notice Retrieves the configuration for a specific plug on a network
Expand Down
61 changes: 32 additions & 29 deletions contracts/protocol/socket/Socket.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
pragma solidity ^0.8.21;

import "./SocketUtils.sol";

import {IPlug} from "../../interfaces/IPlug.sol";
import {PlugDisconnected, InvalidAppGateway} from "../utils/common/Errors.sol";

/**
Expand Down Expand Up @@ -38,35 +40,6 @@ contract Socket is SocketUtils {
string memory version_
) SocketUtils(chainSlug_, owner_, version_) {}

////////////////////////////////////////////////////////
////////////////////// OPERATIONS //////////////////////////
////////////////////////////////////////////////////////
/**
* @notice To send message to a connected remote chain. Should only be called by a plug.
* @param payload bytes to be delivered to the Plug on the siblingChainSlug_
* @param params a 32 bytes param to add details for execution, for eg: fees to be paid for execution
*/
function callAppGateway(
bytes calldata payload,
bytes32 params
) external returns (bytes32 callId) {
PlugConfig memory plugConfig = _plugConfigs[msg.sender];

// if no sibling plug is found for the given chain slug, revert
if (plugConfig.appGateway == address(0)) revert PlugDisconnected();

// creates a unique ID for the message
callId = _encodeCallId(plugConfig.appGateway);
emit AppGatewayCallRequested(
callId,
chainSlug,
msg.sender,
plugConfig.appGateway,
params,
payload
);
}

/**
* @notice Executes a payload that has been delivered by transmitters and authenticated by switchboards
*/
Expand Down Expand Up @@ -137,4 +110,34 @@ contract Socket is SocketUtils {
revert PayloadAlreadyExecuted(payloadExecuted[payloadId_]);
payloadExecuted[payloadId_] = ExecutionStatus.Executed;
}

////////////////////////////////////////////////////////
////////////////////// OPERATIONS //////////////////////////
////////////////////////////////////////////////////////
/**
* @notice To send message to a connected remote chain. Should only be called by a plug.
* @param payload_ bytes to be delivered on EVMx
* @param overrides_ a bytes param to add details for execution, for eg: fees to be paid for execution
*/
function _callAppGateway(
address plug_,
bytes memory overrides_,
bytes memory payload_
) internal returns (bytes32 triggerId) {
PlugConfig memory plugConfig = _plugConfigs[plug_];

// if no sibling plug is found for the given chain slug, revert
if (plugConfig.appGateway == address(0)) revert PlugDisconnected();

// creates a unique ID for the message
triggerId = _encodeTriggerId(plugConfig.appGateway);
emit AppGatewayCallRequested(triggerId, chainSlug, plug_, overrides_, payload_);
}

/// @notice Fallback function that forwards all calls to Socket's callAppGateway
/// @dev The calldata is passed as-is to the gateways
fallback(bytes calldata) external returns (bytes memory) {
bytes memory overrides = IPlug(msg.sender).overrides();
return abi.encode(_callAppGateway(msg.sender, overrides, msg.data));
}
}
12 changes: 7 additions & 5 deletions contracts/protocol/socket/SocketUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ abstract contract SocketUtils is SocketConfig {
// ChainSlug for this deployed socket instance
uint32 public immutable chainSlug;

uint64 public callCounter;
uint64 public triggerCounter;

/**
* @dev keeps track of whether a payload has been executed or not using payload id
Expand Down Expand Up @@ -113,12 +113,14 @@ abstract contract SocketUtils is SocketConfig {
}

// Packs the local plug, local chain slug, remote chain slug and nonce
// callCount++ will take care of call id overflow as well
// callId(256) = localChainSlug(32) | appGateway_(160) | nonce(64)
function _encodeCallId(address appGateway_) internal returns (bytes32) {
// triggerCounter++ will take care of call id overflow as well
// triggerId(256) = localChainSlug(32) | appGateway_(160) | nonce(64)
function _encodeTriggerId(address appGateway_) internal returns (bytes32) {
return
bytes32(
(uint256(chainSlug) << 224) | (uint256(uint160(appGateway_)) << 64) | callCounter++
(uint256(chainSlug) << 224) |
(uint256(uint160(appGateway_)) << 64) |
triggerCounter++
);
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/protocol/utils/common/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ error CallFailed();
error PlugDisconnected();
error InvalidAppGateway();
error AppGatewayAlreadyCalled();
error InvalidInboxCaller();
error InvalidCallerTriggered();
error PromisesNotResolved();
error InvalidPromise();
error InvalidIndex();
Expand Down
6 changes: 3 additions & 3 deletions contracts/protocol/utils/common/Structs.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ struct PlugConfig {
address appGateway;
address switchboard;
}
//inbox:
struct CallFromChainParams {
bytes32 callId;
//trigger:
struct TriggerParams {
bytes32 triggerId;
bytes32 params;
address plug;
address appGateway;
Expand Down
43 changes: 22 additions & 21 deletions contracts/protocol/watcherPrecompile/WatcherPrecompile.sol
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,10 @@ contract WatcherPrecompile is RequestHandler {
maxTimeoutDelayInSeconds = maxTimeoutDelayInSeconds_;
}

// ================== On-Chain Inbox ==================
// ================== On-Chain Trigger ==================

function callAppGateways(
CallFromChainParams[] calldata params_,
TriggerParams[] calldata params_,
uint256 signatureNonce_,
bytes calldata signature_
) external {
Expand All @@ -248,32 +248,29 @@ contract WatcherPrecompile is RequestHandler {
);

for (uint256 i = 0; i < params_.length; i++) {
if (appGatewayCalled[params_[i].callId]) revert AppGatewayAlreadyCalled();
if (appGatewayCalled[params_[i].triggerId]) revert AppGatewayAlreadyCalled();

address appGateway = _decodeAppGateway(params_[i].triggerId);
if (
!watcherPrecompileConfig__.isValidPlug(
params_[i].appGateway,
appGateway,
params_[i].chainSlug,
params_[i].plug
)
) revert InvalidInboxCaller();

appGatewayCalled[params_[i].callId] = true;
IAppGateway(params_[i].appGateway).callFromChain(
params_[i].chainSlug,
params_[i].plug,
params_[i].params,
params_[i].payload
);
) revert InvalidCallerTriggered();

emit CalledAppGateway(
params_[i].callId,
params_[i].chainSlug,
params_[i].plug,
params_[i].appGateway,
params_[i].params,
params_[i].payload
);
appGatewayCaller = appGateway;
appGatewayCalled[params_[i].triggerId] = true;

(bool success, ) = address(appGateway).call(params_[i].payload);
if (!success) {
emit AppGatewayCallFailed(params_[i].triggerId);
} else {
emit CalledAppGateway(params_[i].triggerId);
}
}

appGatewayCaller = address(0);
}

// ================== Helper functions ==================
Expand All @@ -285,4 +282,8 @@ contract WatcherPrecompile is RequestHandler {
function getRequestParams(uint40 requestCount) external view returns (RequestParams memory) {
return requestParams[requestCount];
}

function _decodeAppGateway(bytes32 triggerId_) internal pure returns (address) {
return address(uint160(uint256(triggerId_) >> 64));
}
}
Loading