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 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 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.