Getting Started

Prophet presents a versatile and fully adaptable optimistic oracle solution, transcending the boundaries of conventional dispute resolution modules. With its emphasis on complete control and modularity across all aspects of the system, Prophet is an open-source public good for the Optimism community.

Repositories

Deployments

The addresses of the contracts deployed on Optimism Sepolia will be listed here.

Licensing

The primary license for Prophet contracts is MIT.

Contributors

Prophet was built with ❤️ by Wonderland.

Wonderland is a team of top Web3 researchers, developers, and operators who believe that the future needs to be open-source, permissionless, and decentralized.

DeFi sucks, but Wonderland is here to make it better.

Prophet Framework 101

What is Prophet?

Prophet presents a versatile and fully adaptable optimistic oracle solution, transcending the boundaries of conventional dispute resolution modules. It moves away from a one-fits-all resolution system and provides customizable modules that can be fine-tuned to meet the unique requirements of each user. With its emphasis on complete control and modularity across all aspects of the system, Prophet is an open-source public good for the Optimism community.

  • Optimistic: Prophet is an optimistic oracle, meaning that in most cases a request will be answered without any disputes. This allows for a fast and cheap capturing of the information.
  • Modular: The framework is designed to support countless use cases by enabling the users to choose the logic of their requests. The users can choose from a variety of modules and extensions.
  • Permissionless: Asking for or providing the data requires no approvals from any centralized party. Additionally, anyone is free to expand the system by building new modules and extensions.
  • Public good: Prophet does not extract any value from its users.

Key Concents

Roles

  • Requester creates requests in the Oracle
  • Proposer gets rewards for providing valid answers to the requests
  • Disputer challenges answers and gets paid if the answer is found to be invalid

Request

A request is what is being asked for. Example requests are:

  • What's the price of oil on April 1st?
  • Was the temperature in Madrid above 30 degrees on 1st July 2023?

At any time, a request will be in one of the following states

  1. No response has been proposed yet. In this case either a response can be proposed or, if the submission deadline has passed, the request's state can be changed to finalized without responses, meaning it will never be answered.

  2. A response has been proposed. The response is considered valid until claimed otherwise by a disputer. If undisputed, the response becomes finalized after the submission deadline is over.

  3. A response has been proposed and disputed. Disputing a response usually opens up a window for proposing a new response. If the dispute gets resolved in favor of the proposer, the request can be finalized. If the resolution favors the disputer, the proposer's bond is transferred to the disputer. Inconclusive results are possible, for instance if a vote fails to reach quorum.

  4. The request has been finalized. From this point it's unchangeable and if there is a response, it can be safely used by other contracts.

Response

A response is a proposed answer to a request. The submission is open for anyone matching the criteria defined in the response module. For instance it could be an NFT holder, an address with a sufficient bond or an entity from a list of approved addresses.

Dispute

Disputes are the core mechanism of an optimistic oracle protecting it from malicious actors. A dispute can be raised by anyone meeting the requirements imposed by the dispute module of a particular request. A multitude of options is available for the dispute module, from simple voting to more complex mechanisms.

Dispute modules are designed to reduce the number of calls to the resolution modules, for instance by allowing a bond escalation period before the dispute is escalated to the resolution module.

In some cases a dispute can be resolved on-chain, unlocking atomical resolution and finalization of the request and eliminating the need for a resolution module.

Oracle

This smart-contract coordinates and ensures the correct use and functionality of in-use modules. It's the entry point/proxy for external calls into the modules.

The oracle only has power over storing requests data, everything else is decided by the modules used in the requests.

Modules

Modules are the lego blocks for requests. They're responsible for the logic of the request, such as who is allowed to propose the answers, where to get them, and how to resolve disputes.

Since building a module is permissionless, the users should pay extra attention to the contracts they choose to interact with, verify their safety and compatibility with other modules.

Module-specific logic should be implemented in hooks such as createRequest and finalizeRequest, that are called by the oracle contract when setting up or finalizing a request. They can be used to implement custom logic, such as storing the data in a custom format or sending a notification to a user.

Extensions

Extensions are smart-contracts that are extending the functionality of the modules. They can be used to store data, manage user balances, and more. One example of an extension would be the accounting extension, which is used to keep user funds and streamline user interactions with the oracle by eliminating the need for constant fund transfers.

Core Contracts

The core contracts of the Prophet project are the backbone of the system responsible for keeping track of the data and routing the calls to the appropriate modules.

The core includes:

  • The Oracle contract, which is the main contract that connects different parts of a request
  • The Module abstract contract, which is the base for all modules
  • The interfaces for the different modules, such as IRequestModule, IResponseModule, etc

For more detailed information about each contract, please refer to the respective documentation pages.

For the Request, Response, Dispute, Resolution and Finality modules, please refer to the respective sections in the Modules documentation.

For more technical details about the interfaces of the core contracts, please refer to the Interfaces section in the technical documentation.

⚠️ Please note that the code has not been audited yet, so use it with caution.

Oracle

See IOracle.sol for more details.

1. Introduction

The Oracle serves as the central part of the Prophet framework. It performs the following functions:

  • Managing requests, responses and disputes.
  • Routing function calls to appropriate modules.
  • Keeping data synchronized between different modules.
  • Providing the users with the full picture of their request, response or dispute.

The Oracle does not handle any transfers, utilizing the extensions for that functionality.

2. Contract Details

Key Methods

  • createRequest: Creates a new request.
  • createRequests: Creates multiple requests at once.
  • proposeResponse: Proposes a response to a request.
  • disputeResponse: Disputes a response to a request.
  • escalateDispute: Escalates a dispute to the next level.
  • resolveDispute: Stores the resolution outcome and changes the dispute status.
  • updateDisputeStatus: Updates the status of a dispute.
  • finalize: Finalizes a request.

3. Key Mechanisms & Concepts

Stored data

The oracle keeps almost no data in storage, instead relying on events to help off-chain agents track the state of requests, responses and disputes.

Request, response, dispute IDs

The IDs are calculated as keccak256 hash of the request, response or dispute data. This allows for easy verification of the data integrity and uniqueness.

Finalization

The oracle supports 2 ways of finalizing a request.

  1. In case there is a non-disputed response, the request can be finalized by calling finalize function and providing the final response. The oracle will call finalizeRequest on the modules and mark the request as finalized. Usually the finalizeRequest hook will issue the reward to the proposer.

  2. If no responses have been submitted, or they're all disputed, the request can be finalized by calling finalize function with a response that has its request ID set to 0. The same hook will be executed in all modules, refunding the requester and marking the request as finalized.

4. Gotchas

Request misconfiguration

Due to the modular and open nature of the framework, the oracle does not have any rules or validations, and a request is deemed correct unless it reverts on creation (createRequest hook). It’s the requester’s responsibility to choose sensible parameters and avoid the request being unattractive to proposers and disputers, impossible to answer or finalize.

The same can be said about engaging with a request. Off-chain validation must be done prior to proposing or disputing any response to avoid the loss of funds. We strongly encourage keeping a list of trusted modules and extensions and avoid interactions with unverified ones.

Module

See IModule.sol for more details.

Module is an abstract contract that defines common functions and modifiers. A module is supposed to inherit the abstract contract and implement specific logic in one of the hooks, for example finalizeRequest. All public functions in the contract are callable only by the oracle, and there are internal functions ensuring the integrity of the data being passed around, such as _validateResponse and _validateDispute.

In addition to the abstract contact, we've created interfaces for each type of module:

Each of them inherits the IModule interface and adds additional functions specific to the module type.

Modules

Here you can find the list and the details of each module available in Prophet

Common Parts

You can notice that many modules follow the same structure. This is because they all inherit from the IModule interface which defines the common functions and modifiers that all modules should have.

  • moduleName is required to properly show the module in Prophet UI.
  • RequestParameters is which parameters are required for the request to be processed with the module.
  • decodeRequestData decodes the ABI encoded parameters using the RequestParameters struct and returns them as a list. This is useful for both on-chain and off-chain components.

Best Practices

When building a module, keep in mind these tips to make the module predictable and easier to work with:

  1. Always process the release and refund of the bond within the same module where the bonding initially occurs. This approach enhances composability and allows developers to concentrate on the logic specific to their module.
  2. Typically, a module is designed to function independently. However, there are instances where multiple modules are developed in a manner that necessitates their joint use. For an example take a look at SparseMerkleTreeModule and RootVerificationModule.
  3. When feasible, avoid requiring users to interact directly with the module. Instead, route all calls via the oracle.

Request

Introduction

All modules in the Prophet Framework are designed to handle specific parts of a request's lifecycle and the Request module is responsible for asking for the information and configuring a reward. This includes declaring the source for the response and running any necessary validations or actions specified in the createRequest function.

Prophet's Request modules:

Creating a Request Module

Creating a Request module is as simple as following from the IRequestModule interface and implementing the necessary logic in the createRequest and finalizeRequest hooks, as well as any custom logic.

A good Request module should take care of the following:

  • Defining the RequestParameters struct with the necessary configuration for requests, such as the data source and the reward
  • Providing a way for the requester to withdraw the reward if no valid answer is proposed
  • Securing the hooks with the onlyOracle modifier

Contract Call Request Module

See IContractCallRequestModule.sol for more details.

1. Introduction

The ContractCallRequestModule is a module for requesting on-chain information. It specifies the source and the reward for a correct response.

2. Contract Details

Key Methods

  • decodeRequestData: Decodes request parameters. It returns the target contract address, the function selector, the encoded arguments of the function to call, the accounting extension to bond and release funds, the payment token, and the payment amount.
  • createRequest: Can be used to bond the requester's funds and validate the request parameters.
  • finalizeRequest: Finalizes a request by paying the proposer if there is a valid response, or releasing the requester's bond if no valid response was provided.

Request Parameters

  • target: The address of the contract to get the response from.
  • functionSelector: The function that returns the response to the request.
  • data: The data to pass to the function.
  • accountingExtension: The address holding the bonded tokens. It must implement the IAccountingExtension.sol interface.
  • paymentToken: The ERC20 token used for paying the proposer.
  • paymentAmount: The amount of tokens the proposer will receive for a correct response.

3. Key Mechanisms & Concepts

4. Gotchas

  • The proposers must keep a list of allowed targets and function selectors and only interact with the contracts they trust. One obvious trick is to use transfer as the function to call, which would allow the requester to steal the proposer's funds.
  • Misconfiguring the data or choosing a function that does not exist on the target would render the request impossible to answer.

HTTP Request Module

See IHttpRequestModule.sol for more details.

1. Introduction

The HttpRequestModule is a contract that allows users to request HTTP calls.

2. Contract Details

Key Methods

  • decodeRequestData: Decodes request parameters. It returns the URL, HTTP method, body, accounting extension, payment token, and payment amount from the given data.
  • createRequest: Can be used to bond the requester's funds and validating the request parameters.
  • finalizeRequest: Finalizes a request by paying the proposer if there is a valid response, or releasing the requester's bond if no valid response was provided.

Request Parameters

  • url: The URL to make the HTTP request to.
  • method: The HTTP method to use.
  • body: The query or body parameters to send with the request.
  • accountingExtension: The address of the accounting extension to use.
  • paymentToken: The address of the token to use for payment.
  • paymentAmount: The amount of tokens to pay for a correct response.

3. Key Mechanisms & Concepts

  • The HttpRequestModule uses an enum to represent the HTTP methods (GET, POST).
  • Check out Accounting Extension.

4. Gotchas

  • No support for DELETE, PUT, PATCH because they usually require some sort of authorization.
  • Keep in mind that the call to the URL will likely be made multiple times by different proposers, which is especially important for POST requests.
  • Providing an invalid URL or HTTP method will cause the request to become impossible to answer.

Sparse Merkle Tree Request Module

See ISparseMerkleTreeRequestModule.sol for more details.

1. Introduction

The SparseMerkleTreeRequestModule is a contract that allows a user to request the calculation of a Merkle tree after inserting a set of leaves.

2. Contract Details

Key Methods

  • decodeRequestData: Decodes request parameters. It returns a RequestParameters struct that contains the parameters for the request.
  • createRequest: Can be used to bond the requester's funds and validating the request parameters.
  • finalizeRequest: Finalizes a request by paying the proposer if there is a valid response, or releasing the requester's bond if no valid response was provided.

Request Parameters

  • treeData: The encoded Merkle tree data parameters for the tree verifier.
  • leavesToInsert: The array of leaves to insert into the Merkle tree.
  • treeVerifier: The tree verifier to calculate the root.
  • accountingExtension: The accounting extension to use for the request.
  • paymentToken: The payment token to use for the request.
  • paymentAmount: The payment amount to use for the request.

3. Key Mechanisms & Concepts

  • The SparseMerkleTreeRequestModule uses a Merkle tree to calculate the root from a set of leaves. The verifier contract is used to calculate the Merkle root hash given a set of Merkle tree branches and Merkle tree leaves count.
  • Check out Accounting Extension.

4. Gotchas

  • The module is supposed to be paired with RootVerificationModule.
  • The verifier contract must follow the ITreeVerifier interface, otherwise the proposers won't be able to calculate the correct response.

Response

Introduction

The Response module is a vital part of any request that manages the requirements the requester has for the proposers, such as holding an NFT, being in a pre-defined list of addresses or providing a bond, and pays out the rewards for accepted responses.

Prophet's Response modules:

  • BondedResponseModule that requires a proposer to post a bond first, which will be returned upon request finalization or slashed in case of a successful dispute.

Creating a Response Module

To build a Response module, simply inherit from IResponseModule and the Module abstract contract, create the RequestParameters struct and define the logic for proposing, deleting and finalizing responses.

A Response module should take care of the following:

  • Defining the criteria for proposers to be able to answer the request
  • Setting the rules for the responses, such as validations or deadlines
  • Handling the rewards for proposing a valid response
  • Applying the onlyOracle modifier to the hooks to secure them
  • Releasing the bond if the response ended up being unutilized, meaning it's not accepted nor disputed

While developing a Response module, keep in mind that the criteria that is too narrow might result in a lack of responses, while criteria that is too broad might result in a large number of invalid responses.

Bonded Response Module

See IBondedResponseModule.sol for more details.

1. Introduction

The Bonded Response Module is a contract that allows users to propose a response for a request by bonding tokens.

2. Contract Details

Key Methods

  • decodeRequestData: Decodes request parameters.
  • propose: Proposes a response for a request, bonding the proposer's tokens. A response cannot be proposed after the deadline or if an undisputed response has already been proposed.
  • releaseUnutilizedResponse: Releases the proposer funds if the response is valid and it has not been used to finalize the request.
  • finalizeRequest: Finalizes the request, paying the proposer of the final response.

Request Parameters

  • accountingExtension: The address holding the bonded tokens. It must implement the IAccountingExtension.sol interface.
  • bondToken: The ERC20 token used for bonding.
  • bondSize: The amount of tokens the disputer must bond to be able to dispute a response.
  • deadline: The timestamp at which the module stops accepting new responses for a request and it becomes finalizable.

3. Key Mechanisms & Concepts

  • Early finalization: It is possible for pre-dispute modules to atomically calculate the correct response on-chain, decide on the result of a dispute and finalize the request before its deadline.
  • Dispute window: Prevents proposers from submitting a response 1 block before the deadline and finalizing it in the next block, leaving disputers no time to dispute the response.
  • Unutilized response: A correct response that has not been used to finalize the request. Consider what happens when the first response to a request is disputed maliciously and someone sends a second response with the same content. In that case if the second response isn't disputed and the first one comes back from the dispute and is accepted as the final response, the second proposer should be able to get his bond back.

Dispute

Introduction

The Dispute module is a crucial component of the Prophet Framework that manages the process of challenging responses, improving the security and trustworthiness of the data.

In Prophet, examples of Dispute modules include:

  • BondedDisputeModule that requires a challenger to post a bond first, which will be returned upon successful dispute resolution or slashed in case of an unsuccessful dispute.
  • BondEscalationModule in which the sides take turns increasing the bond until one of them gives up or until they reach a limit.
  • CircuitResolverModule that allows for the dispute to be resolved on-chain.
  • RootVerificationModule that, similarly to the CircuitResolverModule, enables atomical on-chain resolution of disputes.

Dispute Types

  • Pre-dispute: This type of Dispute modules aims to settle disputes before they reach the Resolution module. BondEscalationModule is an example of a pre-dispute module.

  • Atomical dispute: This type of dispute relies on an external contract to atomically resolve the dispute as soon as it's started. In this case the Resolution module might not be needed at all. CircuitResolverModule and RootVerificationModule are examples of atomical dispute modules.

Developing a Dispute Module

When developing a Dispute module, after inheriting the IDisputeModule interface, you should:

  • Define the criteria for challengers to be able to initiate a dispute
  • Set the rules for the disputes, such as validations or deadlines
  • Handle the rewards or slashing resulting from the dispute resolution
  • Specify the next steps if a dispute should be moved to the Resolution module

Ensure that the dispute criteria are not too narrow to prevent valid disputes from being raised. Conversely, criteria that are too broad might result in a large number of unnecessary disputes.

Bonded Dispute Module

See IBondedDisputeModule.sol for more details.

1. Introduction

The Bonded Dispute Module is a contract that allows users to dispute a proposed response by bonding tokens. Depending on the result of the dispute, the tokens are either returned to the disputer or to the proposer (slashed).

2. Contract Details

Key Methods

  • decodeRequestData: Decodes request parameters.
  • disputeResponse: Starts a dispute.
  • onDisputeStatusChange: Is a hook called by the oracle when a dispute status has been updated.
  • disputeEscalated: Called by the oracle when a dispute has been escalated. Not implemented in this module.

Request Parameters

  • accountingExtension: The address holding the bonded tokens. It must implement the IAccountingExtension.sol interface.
  • bondToken: The ERC20 token used for bonding.
  • bondSize: The amount of tokens the disputer must bond to be able to dispute a response.

3. Key Mechanisms & Concepts

Check out Accounting Extension.

4. Gotchas

  • The module does not handle the cases of inconclusive dispute, e.g. if a ERC20 vote has failed to reach the quorum.
  • Choosing a non-ERC20 token might result in disputers not being able to use this module.

Bond Escalation Module

See IBondEscalationModule.sol for more details.

1. Introduction

The Bond Escalation Module is a contract that allows users to have the first dispute of a request go through the bond escalation mechanism. This mechanism allows for a dispute to be escalated by pledging more funds in favor or against the dispute. The module is designed to prevent last-second breaking of ties by adding a tying buffer at the end of the bond escalation deadline.

2. Contract Details

Key Methods

  • decodeRequestData: Decodes request parameters.
  • disputeResponse: Start the bond escalation process. In case of a second and subsequent disputes, the function bonds the disputer's funds but does not start the bond escalation, instead escalating the dispute to the resolution module.
  • onDisputeStatusChange: Handles any changes in the status of a dispute, pays the winning party.
  • disputeEscalated: Called when a dispute has been escalated, putting the bond escalation on hold. It is only possible if there is a tie between the sides of the dispute.
  • pledgeForDispute: Lets a user pledge in favor of a dispute.
  • pledgeAgainstDispute: Lets a user pledge against a dispute.
  • settleBondEscalation: Settles the bond escalation process of a given request, allowing the winning pledgers to withdraw their funds from the bond escalation accounting extension.

Request Parameters

  • accountingExtension: The address of the accounting extension associated with the given request.
  • bondToken: The address of the token associated with the given request.
  • bondSize: The amount to bond to dispute or propose an answer for the given request.
  • maxNumberOfEscalations: The maximum allowed escalations or pledges for each side during the bond escalation process.
  • bondEscalationDeadline: The timestamp at which bond escalation process finishes when pledges are not tied.
  • tyingBuffer: The number of seconds to extend the bond escalation process to allow the losing party to tie if at the end of the initial deadline the pledges weren't tied.
  • disputeWindow: The number of seconds disputers have to challenge the proposed response since its creation.

3. Key Mechanisms & Concepts

  • Bond Escalation: The process of raising stakes and pledging for one of the sides of a dispute. The sides take turns bonding funds until the bond escalation deadline is met. If the number of pledges in favor of the dispute is not equal to the number of pledges against the dispute at the end of the bond escalation deadline plus the tying buffer, the bond escalation accountancy can be settled. In case of a tie, the dispute must be escalated to the resolution module.
  • Pledge: Bonded funds that are used to support or oppose a dispute.

4. Gotchas

  • Only the first dispute of a request can go through the bond escalation mechanism. Any subsequent disputes will be forwarded to the resolution module.
  • After the bond escalation has finished, the winning side should withdraw their funds by calling claimEscalationReward on the bond escalation accounting extension.
  • The funds of the losing side of the bond escalation will be slashed and given to the winners.

Circuit Resolver Module

See ICircuitResolverModule.sol for more details.

1. Introduction

The Circuit Resolver Module is a pre-dispute module that allows disputers to verify a zero-knowledge circuit for a given request and propose it as a response, starting and resolving the dispute atomically.

2. Contract Details

Key Methods

  • decodeRequestData: Decodes request parameters.
  • disputeResponse: Verifies the ZK circuit and compares it to the proposed one. Updates the dispute status after checking if the disputed response is indeed wrong.
  • onDisputeStatusChange: Updates the status of the dispute and resolves it by proposing the correct circuit as a response and finalizing the request.

Request Parameters

  • callData: The encoded data forwarded to the verifier.
  • verifier: The address of the verifier contract.
  • accountingExtension: The accounting extension to use for payments.
  • bondToken: The token to use for payments, it must be the same token that was specified for the response module.
  • bondSize: The size of the payment for winning a dispute, it must be the same amount that was specified for the response module.

3. Key Mechanisms & Concepts

  • Verifier: A contract implementing the verification logic, which will be consulted in case of a dispute.
  • Atomical dispute: With this module, a dispute is initiated and resolved in the same transaction because the answer can be (somewhat expensively) calculated on-chain.

4. Gotchas

  • The disputer is not required to bond any tokens in order to start a dispute, because in case they're wrong the cost of calculating the answer will be the penalty. However, depending on the chosen response module, they might be required to bond as a proposer of a new response.
  • The module relies on the correct implementation of the verifier. If the verifier's logic if flawed, the module may not be able to resolve disputes correctly.

Root Verification Module

See IRootVerificationModule.sol for more details.

1. Introduction

The Root Verification Module is a pre-dispute module that allows disputers to calculate the correct Merkle root for a given request and propose it as a response, starting and resolving the dispute atomically.

2. Contract Details

Key Methods

  • decodeRequestData: Decodes request parameters.
  • disputeResponse: Calculates the correct root and compares it to the proposed one. Updates the dispute status after checking if the disputed response is indeed wrong.
  • onDisputeStatusChange: Updates the status of the dispute and resolves it by proposing the correct root as a response and finalizing the request.

Request Parameters

  • treeData: The Merkle tree.
  • leavesToInsert: The leaves to insert in the tree.
  • treeVerifier: The tree verifier to use to calculate the correct root.
  • accountingExtension: The accounting extension to use for payments.
  • bondToken: The token to use for payments, it must be the same token that was specified for the response module.
  • bondSize: The size of the payment for winning a dispute, it must be the same amount that was specified for the response module.

3. Key Mechanisms & Concepts

  • Tree verifier: A contract implementing the ITreeVerifier interface, which will be consulted in case of a dispute and will provide the correct root for the Merkle tree, taking into consideration the new leaves.
  • Atomical dispute: With this module, a dispute is initiated and resolved in the same transaction because the answer can be (somewhat expensively) calculated on-chain.

4. Gotchas

  • The module is supposed to be paired with the sparse merkle tree module or a similar one.
  • The disputer is not required to bond any tokens in order to start a dispute, because in case they're wrong the cost of calculating the correct root will be the penalty. However, depending on the chosen response module, they might be required to bond as a proposer of a new response.
  • The module relies on the correct implementation of the tree verifier to calculate the Merkle root. If the tree verifier's logic if flawed, the module may not be able to resolve disputes correctly.

Resolution

Introduction

The Resolution module is responsible for providing an answer to a dispute. It is the last step of the dispute resolution process. Because of the vast amount of resolution methods, there is no general guideline for creating a Resolution module but keep in mind that some disputes cannot be resolved, in which case the Resolution module should probably refund all involved parties.

In Prophet, examples of Resolution modules include:

They all follow the IResolutionModule interface.

Arbitrator Module

See IArbitratorModule.sol for more details.

1. Introduction

The Arbitrator Module is a part of the dispute resolution system. It allows an external arbitrator contract to resolve a dispute. The module provides methods to start the arbitration process, resolve the dispute, and get the status and validity of a dispute.

2. Contract Details

Key Methods

  • decodeRequestData: Decodes request parameters.
  • getStatus: Returns the arbitration status of a dispute.
  • isValid: Indicates whether the dispute has been arbitrated.
  • startResolution: Starts the arbitration process by calling resolve on the arbitrator and flags the dispute as Active.
  • resolveDispute: Resolves the dispute by getting the answer from the arbitrator and notifying the oracle.

Request Parameters

  • arbitrator: The address of the arbitrator. The contract must follow the IArbitrator interface.

3. Key Mechanisms & Concepts

The Arbitrator Module uses an external arbitrator contract to resolve disputes. The arbitration process can be in one of three states:

  • Unknown (default)
  • Active
  • Resolved

The process starts with the startResolution function, which sets the dispute status to Active. The resolveDispute function is then used to get the answer from the arbitrator and update the dispute status to Resolved.

4. Gotchas

  • The status of the arbitration is stored in the _disputeData mapping along with the dispute status. They're both packed in a uint256.
  • The startResolution function will revert if the arbitrator address is the address zero.
  • If the chosen arbitrator does not implement resolve nor getAnswer function, the dispute will get stuck in the Active state.

Bond Escalation Resolution Module

See IBondEscalationResolutionModule.sol for more details.

1. Introduction

The BondEscalationResolutionModule is a resolution module that handles the bond escalation resolution process for disputes. During the resolution, the sides take turns pledging for or against a dispute by bonding tokens.

2. Contract Details

Key Methods

  • decodeRequestData: Decodes request parameters.
  • pledgeForDispute: Allows users to pledge in favor of a given dispute.
  • pledgeAgainstDispute: Allows users to pledge against a given dispute.
  • claimPledge: Allows user to claim his corresponding pledges after a dispute is resolved.

Request Parameters

  • accountingExtension: The accounting extension to be used.
  • bondToken: The token to be used for bonding.
  • percentageDiff: The percentage difference for the dispute.
  • pledgeThreshold: The pledge threshold for the dispute.
  • timeUntilDeadline: The time until the main deadline.
  • timeToBreakInequality: The time to break inequality.

3. Key Mechanisms & Concepts

The outcome of a dispute is determined by the total pledges for and against the dispute. If the total pledges for the dispute are greater than the pledges against, the disputer wins. If the total pledges against the dispute are greater than the pledges for, the disputer loses. The difference between this module and the simple voting is the inequality timer that kicks in when the difference in pledges between the sides exceeds a set threshold. When this happens, the side with the lower amount of pledges has a set amount of time to increase their pledges to match the other side. If they fail to do so, the dispute is resolved in favor of the other side.

ERC20 Resolution Module

See IERC20ResolutionModule.sol for more details.

1. Introduction

The ERC20ResolutionModule is a dispute resolution module that decides on the outcome of a dispute based on a vote.

2. Contract Details

Key Methods

  • decodeRequestData: Decodes request parameters.
  • startResolution: Starts the resolution process for a given dispute.
  • castVote: Allows a user to cast votes for a dispute.
  • resolveDispute: Resolves a dispute based on the votes cast.
  • getVoters: Returns the addresses of the voters for a given dispute.

Request Parameters

  • accountingExtension: The accounting extension associated with the request.
  • token: The ERC20 token used for voting.
  • minVotesForQuorum: The minimum number of votes required for a quorum.
  • timeUntilDeadline: The time from the escalation to the voting deadline.

3. Key Mechanisms & Concepts

The ERC20ResolutionModule uses ERC20 tokens as votes for dispute resolution. Users can cast votes for a dispute by calling the castVote function. The number of votes a user can cast is equal to the number of ERC20 tokens they hold.

The resolution process starts with the startResolution function, which sets the start time for the voting phase. Once the voting phase is over, the resolveDispute function is called to resolve the dispute based on the votes cast. If the total number of votes cast meets the minimum requirement for a quorum, the dispute is resolved.

4. Gotchas

  • It is implied that the voters are incentivized to vote either because they're the governing entity of the ERC20 and have a stake in the outcome of the dispute or because they expect to be rewarded by such an entity.
  • The castVote function requires the user to have approved the contract to spend their ERC20 tokens.
  • Setting a time until deadline that's too short may result in voters not being able to participate.
  • Setting the quorum that's too low may result in the dispute being resolved too early and without much participation.

Private ERC20 Resolution Module

See IPrivateERC20ResolutionModule.sol for more details.

1. Introduction

The PrivateERC20ResolutionModule is a contract that allows users to vote on a dispute using ERC20 tokens. The voting process follows a commit/reveal pattern to ensure that votes are kept secret until the voting period ends.

2. Contract Details

Key methods

  • decodeRequestData: Decodes request parameters.
  • startResolution: Starts the committing phase for a dispute.
  • commitVote: Stores a commitment for a vote cast by a voter.
  • revealVote: Reveals a vote cast by a voter.
  • resolveDispute: Resolves a dispute by tallying the votes and executing the winning outcome.
  • computeCommitment: Computes a valid commitment for the revealing phase.

Request Parameters

  • accountingExtension: The address of the accounting extension associated with the given request.
  • votingToken: The address of the token used for voting.
  • minVotesForQuorum: The minimum number of votes required for a dispute to be resolved.
  • committingTimeWindow: The time window for the committing phase.
  • revealingTimeWindow: The time window for the revealing phase.

3. Key Mechanisms & Concepts

  • Committing phase: From the beginning of the dispute until the committing deadline, the votes are free to cast their votes and store their commitments.
  • Revealing phase: After the committing deadline until the revealing deadline, the voters can reveal their votes by providing the commitment and the salt used to generate it.
  • Salt: A random value used to generate the commitment, making it impossible to guess.

4. Gotchas

  • It is implied that the voters are incentivized to vote either because they're the governing entity of the ERC20 and have a stake in the outcome of the dispute or because they expect to be rewarded by such an entity.
  • The commitVote function allows committing multiple times and overwriting a previous commitment.
  • The revealVote function requires the user to have previously approved the module to transfer the tokens.

Finality

Introduction

Finality modules are responsible for executing actions when a request is finalized, such as notifying a contact about the response to a request.

Prophet's Finality modules:

Creating a Finality Module

To build a Finality module, inherit from IFinalityModule and the Module abstract contract, create the RequestParameters struct and define the logic in the finalizeRequest function. Most importantly, make sure to handle the finalization with and without a response.

Callback Module

See ICallbackModule.sol for more details.

1. Introduction

The Callback Module is a finality module that allows users to call a function on a contract as a result of a request being finalized. It is useful to notify a contract about the outcome of a request.

2. Contract Details

Key Methods

  • decodeRequestData: Decodes request parameters.
  • finalizeRequest: Executing the callback call on the target.

Request Parameters

  • target: The target address for the callback.
  • data: The calldata forwarded to the target.

3. Key Mechanisms & Concepts

As any finality module, the CallbackModule implements the finalizeRequest function which executes the chosen function with the given parameters on the target contract.

4. Gotchas

  • The success of the callback call in finalizeRequest is purposely not checked, specifying a function or parameters that lead to a revert will not stop the request from being finalized.

Multiple Callbacks Module

See IMultipleCallbacksModule.sol for more details.

1. Introduction

The MultipleCallbacksModule is a finality module that allows users to make multiple calls to different contracts as a result of a request being finalized. This module is useful when a single request needs to trigger actions in multiple contracts.

2. Contract Details

Key Methods

  • decodeRequestData: Decodes request parameters. The returned data includes the target addresses for the callback and the calldata forwarded to the targets.
  • finalizeRequest: Finalizes the request by executing the callback calls on the targets.

Request Parameters

  • targets: The target addresses for the callbacks.
  • data: The calldata forwarded to the targets.

3. Key Mechanisms & Concepts

The MultipleCallbacksModule works by storing the target addresses and the calldata for each request. When a request is finalized, the module executes the callback calls on the targets using the stored data.

4. Gotchas

  • The success of the callback calls in finalizeRequest is purposely not checked, specifying a function or parameters that lead to a revert will not stop the request from being finalized.
  • All targets must be contracts.

Extensions

Extensions are smart contracts that expand the functionality of modules. They're not required to be used but can provide safe space for storing the user balances outside of modules, making interactions with the Oracle easier. Extensions are supposed to be reused by multiple modules, handling multiple requests at the same time.

Prophet's shipped with 2 extensions:

Accounting Extension

See IAccountingExtension.sol for more details.

1. Introduction

The Accounting Extension is a contract that allows users to deposit and bond funds to be used for payments and disputes. It provides a way to manage user balances within the system, supporting frictionless interactions with the Oracle and the modules.

2. Contract Details

Key Methods

  • deposit: Allows a user to deposit a specific amount of a token into the accounting extension. If ETH is being deposited, it is wrapped to WETH.
  • withdraw: By calling this function, a user can withdraw a specific amount of a token from the accounting extension.
  • bond: Allows a user to lock a specific amount of a token for a specific request. The tokens stay in the accounting extension and will not be withdrawable until they are released by a module.
  • release: Allows a module to release a specific amount of a token that was previously bonded to a request. The tokens will be moved back to the user's balance.
  • pay: Transfers a specific amount of a bonded token from the payer to the receiver. This function can only be called by a module.

3. Key Mechanisms & Concepts

  • Deposits: Users can deposit tokens into the Accounting Extension. These deposits are tracked in a mapping that associates each user's address with their balance of each token. Deposits can be made in any ERC20 token, including wrapped Ether (WETH).

  • Withdrawals: Users can withdraw their deposited tokens at any time, provided they have sufficient balance. The withdrawal operation reduces the user's balance in the Accounting Extension and transfers the tokens back to the user's address. Locked tokens can't be withdrawn until they're released by a module.

  • Bonding: Users can lock their tokens up to be allowed to participate in a request. Tokens stay in the accounting extension but they cannot be withdrawn until the request is finalized or the tokens are released.

  • Payments: The Accounting Extension allows for payments to be made from one user to another. This usually means rewards for correct proposers and disputers and slashing malicious actors. It's done by unlocking and transferring the bonded tokens from the payer to the receiver's balance. Payments can only be initiated by modules.

  • Releasing Bonds: Bonds can be released by allowed modules, which moves the bonded tokens back to the user's balance, making them available for withdrawal or bonding to a different request.

4. Gotchas

  • Before depositing ERC20 tokens, users must first approve the Accounting Extension to transfer the tokens on their behalf.
  • Users can only withdraw tokens that are not currently bonded. If a user has bonded tokens for a request, those tokens are locked until they are released by an allowed module. Attempting to withdraw bonded tokens will result in an error. Attempting to slash or pay out tokens that are not locked will also result in a transaction being reverted.
  • The contract supports any ERC20 token, including wrapped Ether (WETH). However, if a user tries to deposit a non-ERC20 token or a token that the contract otherwise doesn't support, the transaction will fail.

Bond Escalation Accounting Extension

See IBondEscalationAccounting.sol for more details.

1. Introduction

The BondEscalationAccounting contract is an extension that allows users to deposit and pledge funds to be used for bond escalation. It provides mechanisms for pledging tokens and paying out rewards to the winning pledgers.

2. Contract Details

Key Methods

  • deposit: Allows a user to deposit a specific amount of a token into the accounting extension. If ETH is being deposited, it is wrapped to WETH.
  • withdraw: By calling this function, a user can withdraw a specific amount of a token from the accounting extension.
  • pledge: Allows a user to pledge a certain amount of tokens for a specific dispute. The pledged tokens are deducted from the user's balance and added to the total pledges for the dispute.
  • onSettleBondEscalation: Unlocks the rewards for the winners.
  • claimEscalationReward: Calculates and transfers the caller's part of the reward to them.
  • releasePledge: Allows a module to release a user's tokens.

3. Key Mechanisms & Concepts

  • Pledging: Users can pledge tokens for or against a dispute. The pledged tokens are locked and cannot be used until the dispute is resolved.

  • Deposits: Users can deposit tokens into the extension. Deposits can be made in any ERC20 token, ETH deposits will be converted to WETH.

  • Withdrawals: Users can withdraw their tokens at any time. The withdrawal operation reduces the user's balance in the extension and transfers the tokens back to the user's address. Locked tokens can't be withdrawn until they're released by a module.

4. Gotchas

  • Before depositing ERC20 tokens, users must first approve the extension to transfer the tokens on their behalf.

Periphery

Sparse Merkle Tree Verifier

See ITreeVerifier.sol for more details.

1. Introduction

The SparseMerkleTreeL32Verifier contract is an example of a verifier contract that implements the ITreeVerifier interface. It is supposed to be used in tandem with the RootVerificationModule.

2. Contract Details

Key Methods

The main method in this contract is calculateRoot that calculates a new root from the given one and the leaves to be inserted. The contract expects the tree to have at most 32 levels of depth.

3. Key Mechanisms & Concepts

The contract uses the MerkleLib library for handling operations related to the Merkle tree.

Libraries

MerkleLib

1. Introduction

The MerkleLib is a Solidity library that provides functionality for managing an incremental Merkle tree. The library includes functions for inserting nodes into the tree and calculating the root of the tree.

The library is a part of the Connext monorepo.

2. Contract Details

Key Methods

  • insert: Inserts a given node (leaf) into the Merkle tree. It operates on an in-memory tree and returns an updated version of that tree. If the tree is already full, it reverts the transaction.

3. Key Mechanisms & Concepts

The MerkleLib uses a struct Tree to represent the Merkle tree. This struct contains the current branch of the tree and the number of inserted leaves in the tree.

The library also defines a set of constants Z_i that represent the hash values at different heights for a binary tree with leaf values equal to 0. These constants are used to shortcut calculation in root calculation functions.