> For the complete documentation index, see [llms.txt](https://docs-legacy.kleros.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs-legacy.kleros.io/developer/arbitration-by-example/twopartyarbitrable.sol.md).

# TwoPartyArbitrable.sol

```solidity
pragma solidity ^0.4.15;
import "./Arbitrable.sol";

/** @title Two-Party Arbitrable
 *  @dev A contract between two parties which can be arbitrated. Both parties has to pay for the arbitration fee. The winning party will get its fee refunded.
 *  To develop a contract inheriting from this one, you need to:
 *  - Redefine RULING_OPTIONS to explain the consequences of the possible rulings.
 *  - Redefine executeRuling while still calling super.executeRuling to implement the results of the arbitration.
 */
contract TwoPartyArbitrable is Arbitrable {
    uint public timeout; // Time in second a party can take before being considered unresponding and lose the dispute.
    uint8 public amountOfChoices;
    address public partyA;
    address public partyB;
    uint public partyAFee; // Total fees paid by the partyA.
    uint public partyBFee; // Total fees paid by the partyB.
    uint public lastInteraction; // Last interaction for the dispute procedure.
    uint public disputeID;
    enum Status {NoDispute, WaitingPartyA, WaitingPartyB, DisputeCreated, Resolved}
    Status public status;

    uint8 constant PARTY_A_WINS = 1;
    uint8 constant PARTY_B_WINS = 2;
    string constant RULING_OPTIONS = "Party A wins;Party B wins"; // A plain English of what rulings do. Need to be redefined by the child class.

    modifier onlyPartyA{require(msg.sender == partyA, "Can only be called by party A."); _;}
    modifier onlyPartyB{require(msg.sender == partyB, "Can only be called by party B."); _;}
    modifier onlyParty{require(msg.sender == partyA || msg.sender == partyB, "Can only be called by party A or party B."); _;}

    enum Party {PartyA, PartyB}

    /** @dev Indicate that a party has to pay a fee or would otherwise be considered as loosing.
     *  @param _party The party who has to pay.
     */
    event HasToPayFee(Party _party);

    /** @dev Constructor. Choose the arbitrator.
     *  @param _arbitrator The arbitrator of the contract.
     *  @param _timeout Time after which a party automatically loose a dispute.
     *  @param _partyB The recipient of the transaction.
     *  @param _amountOfChoices The number of ruling options available.
     *  @param _arbitratorExtraData Extra data for the arbitrator.
     *  @param _metaEvidence Link to the meta-evidence.
     */
    constructor(
        Arbitrator _arbitrator,
        uint _timeout,
        address _partyB,
        uint8 _amountOfChoices,
        bytes _arbitratorExtraData,
        string _metaEvidence
    )
        Arbitrable(_arbitrator,_arbitratorExtraData)
        public
    {
        timeout = _timeout;
        partyA = msg.sender;
        partyB = _partyB;
        amountOfChoices = _amountOfChoices;
        emit MetaEvidence(0, _metaEvidence);
    }


    /** @dev Pay the arbitration fee to raise a dispute. To be called by the party A. UNTRUSTED.
     *  Note that the arbitrator can have createDispute throw, which will make this function
     *  throw and therefore lead to a party being timed-out.
     *  This is not a vulnerability as the arbitrator can rule in favor of one party anyway.
     */
    function payArbitrationFeeByPartyA() public payable onlyPartyA {
        uint arbitrationCost = arbitrator.arbitrationCost(arbitratorExtraData);
        partyAFee += msg.value;
        require(
            partyAFee >= arbitrationCost,
            "Not enough ETH to cover arbitration costs."
        ); // Require that the total pay at least the arbitration cost.
        require(status < Status.DisputeCreated, "Dispute has already been created."); // Make sure a dispute has not been created yet.

        lastInteraction = now;
        // The partyB still has to pay. This can also happens if he has paid, but arbitrationCost has increased.
        if (partyBFee < arbitrationCost) {
            status = Status.WaitingPartyB;
            emit HasToPayFee(Party.PartyB);
        } else { // The partyB has also paid the fee. We create the dispute
            raiseDispute(arbitrationCost);
        }
    }


    /** @dev Pay the arbitration fee to raise a dispute. To be called by the party B. UNTRUSTED.
     *  Note that this function mirror payArbitrationFeeByPartyA.
     */
    function payArbitrationFeeByPartyB() public payable onlyPartyB {
        uint arbitrationCost = arbitrator.arbitrationCost(arbitratorExtraData);
        partyBFee += msg.value;
        require(
            partyBFee >= arbitrationCost,
            "Not enough ETH to cover arbitration costs."
        ); // Require that the total pay at least the arbitration cost.
        require(status < Status.DisputeCreated, "Dispute has already been created."); // Make sure a dispute has not been created yet.

        lastInteraction = now;
        // The partyA still has to pay. This can also happens if he has paid, but arbitrationCost has increased.
        if (partyAFee < arbitrationCost) {
            status = Status.WaitingPartyA;
            emit HasToPayFee(Party.PartyA);
        } else { // The partyA has also paid the fee. We create the dispute
            raiseDispute(arbitrationCost);
        }
    }

    /** @dev Create a dispute. UNTRUSTED.
     *  @param _arbitrationCost Amount to pay the arbitrator.
     */
    function raiseDispute(uint _arbitrationCost) internal {
        status = Status.DisputeCreated;
        disputeID = arbitrator.createDispute.value(_arbitrationCost)(amountOfChoices,arbitratorExtraData);
        emit Dispute(arbitrator, disputeID, 0, 0);
    }

    /** @dev Reimburse partyA if partyB fails to pay the fee.
     */
    function timeOutByPartyA() public onlyPartyA {
        require(status == Status.WaitingPartyB, "Not waiting for party B.");
        require(now >= lastInteraction + timeout, "The timeout time has not passed.");

        executeRuling(disputeID,PARTY_A_WINS);
    }

    /** @dev Pay partyB if partyA fails to pay the fee.
     */
    function timeOutByPartyB() public onlyPartyB {
        require(status == Status.WaitingPartyA, "Not waiting for party A.");
        require(now >= lastInteraction + timeout, "The timeout time has not passed.");

        executeRuling(disputeID,PARTY_B_WINS);
    }

    /** @dev Submit a reference to evidence. EVENT.
     *  @param _evidence A link to an evidence using its URI.
     */
    function submitEvidence(string _evidence) public onlyParty {
        require(status >= Status.DisputeCreated, "The dispute has not been created yet.");
        emit Evidence(arbitrator, 0, msg.sender, _evidence);
    }

    /** @dev Appeal an appealable ruling.
     *  Transfer the funds to the arbitrator.
     *  Note that no checks are required as the checks are done by the arbitrator.
     *  @param _extraData Extra data for the arbitrator appeal procedure.
     */
    function appeal(bytes _extraData) public onlyParty payable {
        arbitrator.appeal.value(msg.value)(disputeID,_extraData);
    }

    /** @dev Execute a ruling of a dispute. It reimburse the fee to the winning party.
     *  This need to be extended by contract inheriting from it.
     *  @param _disputeID ID of the dispute in the Arbitrator contract.
     *  @param _ruling Ruling given by the arbitrator. 1 : Reimburse the partyA. 2 : Pay the partyB.
     */
    function executeRuling(uint _disputeID, uint _ruling) internal {
        require(_disputeID == disputeID, "Wrong dispute ID.");
        require(_ruling <= amountOfChoices, "Invalid ruling.");

        // Give the arbitration fee back.
        // Note that we use send to prevent a party from blocking the execution.
        // In both cases sends the highest amount paid to avoid ETH to be stuck in
        // the contract if the arbitrator lowers its fee.
        if (_ruling==PARTY_A_WINS)
            partyA.send(partyAFee > partyBFee ? partyAFee : partyBFee);
        else if (_ruling==PARTY_B_WINS)
            partyB.send(partyAFee > partyBFee ? partyAFee : partyBFee);

        status = Status.Resolved;
    }

}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs-legacy.kleros.io/developer/arbitration-by-example/twopartyarbitrable.sol.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
