Files
tycho-execution/foundry/src/CallbackVerificationDispatcher.sol
2025-01-24 16:55:21 -05:00

80 lines
2.5 KiB
Solidity

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;
import "@interfaces/ICallbackVerifier.sol";
error CallbackVerificationDispatcher__UnapprovedVerifier();
error CallbackVerificationDispatcher__NonContractVerifier();
/**
* @title Dispatch callback verification to external contracts
* @author PropellerHeads Devs
* @dev Provides the ability call external contracts to perform callback
* verification. This allows dynamically adding new supported protocols
* without needing to upgrade any contracts.
*
* Note Verifier contracts need to implement the ICallbackVerifier interface
*/
contract CallbackVerificationDispatcher {
mapping(address => bool) public callbackVerifiers;
/**
* @dev Calls a callback verifier. This should revert if the callback verification fails.
*/
// slither-disable-next-line dead-code
function _callVerifyCallback(bytes calldata data)
internal
returns (
uint256 amountOwed,
uint256 amountReceived,
address tokenOwed,
uint16 dataOffset
)
{
address verifier;
bytes4 decodedSelector;
bytes memory verifierData;
(verifier, decodedSelector, verifierData) =
_decodeVerifierAndSelector(data);
if (!callbackVerifiers[verifier]) {
revert CallbackVerificationDispatcher__UnapprovedVerifier();
}
bytes4 selector = decodedSelector == bytes4(0)
? ICallbackVerifier.verifyCallback.selector
: decodedSelector;
address sender = msg.sender;
// slither-disable-next-line low-level-calls
(bool success, bytes memory result) = verifier.staticcall(
abi.encodeWithSelector(selector, sender, verifierData)
);
if (!success) {
if (result.length > 0) {
revert(string(result));
} else {
revert("Callback verification failed");
}
}
(amountOwed, amountReceived, tokenOwed, dataOffset) =
abi.decode(result, (uint256, uint256, address, uint16));
}
// slither-disable-next-line dead-code
function _decodeVerifierAndSelector(bytes calldata data)
internal
pure
returns (address verifier, bytes4 selector, bytes memory verifierData)
{
require(data.length >= 20, "Invalid data length");
verifier = address(uint160(bytes20(data[:20])));
selector = bytes4(data[20:24]);
verifierData = data[24:];
}
}