contract StaticCallProxy {

    using LibBytes for bytes;

    // Id of this proxy.
    bytes4 constant internal PROXY_ID = bytes4(keccak256("StaticCall(address,bytes,bytes32)"));

    /// @dev Makes a staticcall to a target address and verifies that the data returned matches the expected return data.
    /// @param assetData Byte array encoded with staticCallTarget, staticCallData, and expectedCallResultHash
    /// @param from This value is ignored.
    /// @param to This value is ignored.
    /// @param amount This value is ignored.
    function transferFrom(
        bytes calldata assetData,
        address from,
        address to,
        uint256 amount
    )
        external
        view
    {
        // Decode params from `assetData`
        (
            address staticCallTarget,
            bytes memory staticCallData,
            bytes32 expectedReturnDataHash
        ) = abi.decode(
            assetData.sliceDestructive(4, assetData.length),
            (address, bytes, bytes32)
        );

        // Execute staticcall
        (bool success, bytes memory returnData) = staticCallTarget.staticcall(staticCallData);

        // Revert with returned data if staticcall is unsuccessful
        if (!success) {
            assembly {
                revert(add(returnData, 32), mload(returnData))
            }
        }

        // Revert if hash of return data is not as expected
        bytes32 returnDataHash = keccak256(returnData);
        require(
            expectedReturnDataHash == returnDataHash,
            "UNEXPECTED_STATIC_CALL_RESULT"
        );
    }

    /// @dev Gets the proxy id associated with the proxy address.
    /// @return Proxy id.
    function getProxyId()
        external
        pure
        returns (bytes4)
    {
        return PROXY_ID;
    }
}
// solhint-disable no-unused-vars
function getProxyId()
    external
    pure
    returns (bytes4)
{
    return PROXY_ID;
}

/// @dev Gets the proxy id associated with the proxy address.
/// @return Proxy id.