Web

Actively in Development

Our team is currently working on this feature. If you experience any bugs, please let us know on our Discord. We appreciate your patience.

Existing web applications including finance, social media, government, ecommerce and many other types of services contain valuable information and can be turned into great data sources.

With vlayer, you can leverage this data in smart contracts.

Web Proofs

Web Proofs provide cryptographic proof of web data served by any HTTPS server, allowing developers to use this data in smart contracts. Only a small subset of the required data is published on-chain.

Web Proofs ensure that the data received has not been tampered with. Without Web Proofs, proving this on-chain is difficult, especially when aiming for an automated and trusted solution.

Example Prover

Let's say we want to mint an NFT for a wallet address linked to a specific X/Twitter handle.

Here’s a sample Prover contract:

import {Strings} from "@openzeppelin-contracts/utils/Strings.sol";
import {Proof} from "vlayer-0.1.0/Proof.sol";
import {Prover} from "vlayer-0.1.0/Prover.sol";
import {Web, WebProof, WebProofLib, WebLib} from "vlayer-0.1.0/WebProof.sol";

contract WebProofProver is Prover {
    using Strings for string;
    using WebProofLib for WebProof;
    using WebLib for Web;

    string dataUrl = "https://api.x.com/1.1/account/settings.json";

    function main(WebProof calldata webProof, address account)
        public
        view
        returns (Proof memory, string memory, address)
    {
        Web memory web = webProof.verify(dataUrl);

        string memory screenName = web.jsonGetString("screen_name");

        return (proof(), screenName, account);
    }
}

What happens in the above code?

  1. Setup the Prover contract:

    • WebProofProver inherits from the Prover contract, enabling off-chain proving of web data.
    • The main function receives a WebProof, which contains a signed transcript of an HTTPS session (see the chapter from JS section on how to obtain WebProof Security Considerations section for details about the TLS Notary).
  2. Verify the Web Proof:

    The call to webProof.verify(dataUrl) does the following:

    • Verifies the HTTPS transcript.
    • Verifies the Notary's signature on the transcript.
    • Ensures the Notary is on the list of trusted notaries (via their signing key).
    • Confirms the data comes from the expected domain (api.x.com in this case).
    • Check whether the HTTPS data comes from the expected dataUrl.
    • Ensures that the server's SSL certificate and its chain of authority are verified.
    • Retrieves the plain text transcript for further processing.
  3. Extract the relevant data:

    web.jsonGetString("screen_name") extracts the screen_name from the JSON response.

  4. Return the results:

    If everything checks out, the function returns the proof placeholder, screenName, and the account.

If there are no errors and the proof is valid, the data is ready for on-chain verification.

💡 Try it Now

To run the above example on your computer, type the following command in your terminal:

vlayer init --template web-proof

This command will download all the necessary artifacts to your project.
The next steps are explained in Running example

Example Verifier

The contract below verifies provided Web Proof and mints a unique NFT for the Twitter/X handle owner’s wallet address.

import {WebProofProver} from "./WebProofProver.sol";
import {Proof} from "vlayer/Proof.sol";
import {Verifier} from "vlayer/Verifier.sol";

import {ERC721} from "@openzeppelin-contracts/token/ERC721/ERC721.sol";

contract WebProofVerifier is Verifier, ERC721 {
    address public prover;

    constructor(address _prover) ERC721("TwitterNFT", "TNFT") {
        prover = _prover;
    }

    function verify(Proof calldata, string memory username, address account)
        public
        onlyVerified(prover, WebProofProver.main.selector)
    {
        uint256 tokenId = uint256(keccak256(abi.encodePacked(username)));
        require(_ownerOf(tokenId) == address(0), "User has already minted a TwitterNFT");

        _safeMint(account, tokenId);
    }
}

What’s happening here?

  1. Set up the Verifier:

    • The prover variable stores the address of the Prover contract that generated the proof.
    • The WebProofProver.main.selector gets the selector for the WebProofProver.main() function.
    • WebProofVerifier inherits from Verifier to access the onlyVerified modifier, which ensures the proof is valid.
    • WebProofVerifier also inherits from ERC721 to support NFTs.
  2. Verification checks:

    The tokenId (a hash of the handle) must not already be minted.

  3. Mint the NFT:

    Once verified, a unique TwitterNFT is minted for the user.

And that's it!

As you can see, Web Proofs can be a powerful tool for building decentralized applications by allowing trusted off-chain data to interact with smart contracts.

Security Considerations

The Web Proof feature is based on the TLSNotary protocol. Web data is retrieved from an HTTP endpoint and it's integrity and authenticity during the HTTP session is verified using the Transport Layer Security (TLS) protocol (the "S" in HTTPS), which secures most modern encrypted connections on the Internet. Web Proofs ensure the integrity and authenticity of web data after the HTTPS session finishes by extending the TLS protocol. A designated server, called Notary, joins the HTTPS session between the client and the server and can cryptographically certify its contents.

From privacy perspective, it is important to note that the Notary server never has access to the plaintext transcript of the connection and therefore, Notary can never steal client data and pretend to be client. Furthermore, the transcript can be redacted (i.e. certain parts can be removed) by the client, making these parts of the communication not accessible by Prover and vlayer infrastructure running the Prover.

Trust Assumptions

It is important to understand that the Notary is a trusted party in the above setup. Since the Notary certifies the data, a malicious Notary could collude with a malicious client to create fake proofs that would still be successfully verified by Prover. Currently vlayer runs it's own Notary server, which means that vlayer needs to be trusted to certify HTTPS sessions.

Currently vlayer also needs to be trusted when passing additional data (data other than the Web Proof itself) to Prover smart contract, e.g. account in the example above. The Web Proof could be hijacked before running Prover and additional data, different from the original, could be passed to Prover, e.g. an attacker could pass their own address as account in our WebProofProver example. Before going to production this will be addressed by making the setup trustless through an association of the additional data with a particular Web Proof in a way that's impossible to forge.

vlayer will publish a roadmap outlining how it will achieve a high level of security when using the Notary service.