diff --git a/contracts/interfaces/ISocket.sol b/contracts/interfaces/ISocket.sol index 5727abee..60729a00 100644 --- a/contracts/interfaces/ISocket.sol +++ b/contracts/interfaces/ISocket.sol @@ -16,6 +16,12 @@ interface ISocket { */ event ExecutionSuccess(bytes32 payloadId, bytes returnData); + /** + * @notice emits the status of payload after external call + * @param payloadId msg id which is executed + */ + event ExecutionFailed(bytes32 payloadId, bytes returnData); + /** * @notice emits the config set by a plug for a remoteChainSlug * @param plug address of plug on current chain diff --git a/contracts/mock/MockSocket.sol b/contracts/mock/MockSocket.sol index 11ff3930..1ffdbd03 100644 --- a/contracts/mock/MockSocket.sol +++ b/contracts/mock/MockSocket.sol @@ -61,17 +61,23 @@ contract MockSocket is ISocket { */ error LowGasLimit(); error InvalidSlug(); - error ExecutionFailed(); //////////////////////////////////////////////////////////// ////////////////////// State Vars ////////////////////////// //////////////////////////////////////////////////////////// uint64 public callCounter; uint32 public chainSlug; + + enum ExecutionStatus { + NotExecuted, + Executed, + Reverted + } + /** * @dev keeps track of whether a payload has been executed or not using payload id */ - mapping(bytes32 => bool) public payloadExecuted; + mapping(bytes32 => ExecutionStatus) public payloadExecuted; constructor(uint32 chainSlug_, address, address, address, string memory) { chainSlug = chainSlug_; diff --git a/contracts/protocol/socket/Socket.sol b/contracts/protocol/socket/Socket.sol index 7de9a6ff..67720475 100644 --- a/contracts/protocol/socket/Socket.sol +++ b/contracts/protocol/socket/Socket.sol @@ -23,7 +23,7 @@ contract Socket is SocketUtils { /** * @dev Error emitted when a payload has already been executed */ - error PayloadAlreadyExecuted(); + error PayloadAlreadyExecuted(ExecutionStatus status); /** * @dev Error emitted when the executor is not valid */ @@ -39,7 +39,6 @@ contract Socket is SocketUtils { */ error LowGasLimit(); error InvalidSlug(); - error ExecutionFailed(); error DeadlinePassed(); //////////////////////////////////////////////////////////// @@ -47,10 +46,16 @@ contract Socket is SocketUtils { //////////////////////////////////////////////////////////// uint64 public callCounter; + enum ExecutionStatus { + NotExecuted, + Executed, + Reverted + } + /** * @dev keeps track of whether a payload has been executed or not using payload id */ - mapping(bytes32 => bool) public payloadExecuted; + mapping(bytes32 => ExecutionStatus) public payloadExecuted; constructor( uint32 chainSlug_, @@ -96,9 +101,10 @@ contract Socket is SocketUtils { bytes memory transmitterSignature_ ) external payable returns (bytes memory) { // make sure payload is not executed already - if (payloadExecuted[params_.payloadId]) revert PayloadAlreadyExecuted(); + if (payloadExecuted[params_.payloadId] != ExecutionStatus.NotExecuted) + revert PayloadAlreadyExecuted(payloadExecuted[params_.payloadId]); // update state to make sure no reentrancy - payloadExecuted[params_.payloadId] = true; + payloadExecuted[params_.payloadId] = ExecutionStatus.Executed; if (params_.deadline < block.timestamp) revert DeadlinePassed(); @@ -165,8 +171,13 @@ contract Socket is SocketUtils { value: msg.value }(payload_); - if (!success) revert ExecutionFailed(); - emit ExecutionSuccess(payloadId_, returnData); + if (!success) { + payloadExecuted[payloadId_] = ExecutionStatus.Reverted; + emit ExecutionFailed(payloadId_, returnData); + } else { + emit ExecutionSuccess(payloadId_, returnData); + } + return returnData; } diff --git a/contracts/protocol/watcherPrecompile/WatcherPrecompile.sol b/contracts/protocol/watcherPrecompile/WatcherPrecompile.sol index 3ab83ee4..9f12c7d9 100644 --- a/contracts/protocol/watcherPrecompile/WatcherPrecompile.sol +++ b/contracts/protocol/watcherPrecompile/WatcherPrecompile.sol @@ -320,7 +320,7 @@ contract WatcherPrecompile is WatcherPrecompileConfig, Initializable { resolvedPromises_[i].returnData[j] ); - if (!success) continue; + if (!success) break; emit PromiseResolved(resolvedPromises_[i].payloadId, success, next[j]); } }