Skip to content

Commit

Permalink
feat(composed-arbitrable): finish proxy example
Browse files Browse the repository at this point in the history
  • Loading branch information
epiqueras committed Sep 27, 2018
1 parent 8836aed commit 6df2f6d
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ contract MultiPartyAgreements is Arbitrable {
bytes _extraData,
uint _arbitrationFeesWaitingTime,
Arbitrator _arbitrator
) public {
) internal {
require(agreements[_agreementID].creator == address(0), "The supplied agreement ID is already being used.");
require(_parties.length <= 10, "There cannot be more than 10 parties.");
agreements[_agreementID] = Agreement({
Expand Down Expand Up @@ -87,4 +87,36 @@ contract MultiPartyAgreements is Arbitrable {
executeAgreementRuling(_agreementID, _ruling);
agreement.executed = true;
}

/* External Views */

/** @dev Gets the info on the specified agreement.
* @param _agreementID The ID of the agreement.
* @return The info.
*/
function getAgreementInfo(bytes32 _agreementID) external view returns(
address creator,
address[] parties,
uint numberOfChoices,
bytes extraData,
uint arbitrationFeesWaitingTime,
Arbitrator arbitrator,
uint disputeID,
bool disputed,
bool appealed,
uint ruling,
bool executed
) {
creator = agreements[_agreementID].creator;
parties = agreements[_agreementID].parties;
numberOfChoices = agreements[_agreementID].numberOfChoices;
extraData = agreements[_agreementID].extraData;
arbitrationFeesWaitingTime = agreements[_agreementID].arbitrationFeesWaitingTime;
arbitrator = agreements[_agreementID].arbitrator;
disputeID = agreements[_agreementID].disputeID;
disputed = agreements[_agreementID].disputed;
appealed = agreements[_agreementID].appealed;
ruling = agreements[_agreementID].ruling;
executed = agreements[_agreementID].executed;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
pragma solidity ^0.4.24;
pragma experimental ABIEncoderV2;

import "../proxy/ArbitrableProxyUser.sol";

/**
* @title TwoPartyArbitrableEscrowPaymentProxyUser
* @author Enrique Piqueras - <epiquerass@gmail.com>
* @dev Implementation of a two party arbitrable escrow service using the `ArbitrableProxyUser` contract.
*/
contract TwoPartyArbitrableEscrowPaymentProxyUser is ArbitrableProxyUser {
/* Structs */

struct Payment {
uint value;
uint createdAt;
uint timeOut;
bool executed;
}

/* Storage */

mapping(bytes32 => Payment) public payments;

/* Constructor */

/** @dev Constructs the `TwoPartyArbitrableEscrowPaymentProxyUser` contract.
* @param _arbitrableProxy The arbitrable proxy to use.
*/
constructor(ArbitrableProxy _arbitrableProxy) public ArbitrableProxyUser(_arbitrableProxy) {}

/* External */

/** @dev Creates an escrowed payment.
* @param _paymentID The ID of the payment.
* @param _metaEvidence The meta evidence for the potential dispute.
* @param _to The receiver of the payment.
* @param _arbitrationFeesWaitingTime The maximum time to wait for arbitration fees if the dispute is raised.
* @param _arbitrator The arbitrator to use for the potential dispute.
* @param _timeOut The time to wait before executing the payment if the dispute is not raised.
*/
function createPayment(
bytes32 _paymentID,
string _metaEvidence,
address _to,
uint _arbitrationFeesWaitingTime,
Arbitrator _arbitrator,
uint _timeOut
) external payable {
require(msg.value > 0, "Payment must be more than zero.");
address[] memory _parties = new address[](2);
_parties[0] = msg.sender;
_parties[1] = _to;
arbitrableProxy.createAgreement(
_paymentID,
_metaEvidence,
_parties,
2,
new bytes(0),
_arbitrationFeesWaitingTime,
_arbitrator
);
payments[_paymentID] = Payment({
value: msg.value,
createdAt: now,
timeOut: _timeOut,
executed: false
});
}

/** @dev Executes a payment that has already timed out and is not disputed.
* @param _paymentID The ID of the payment.
*/
function executePayment(bytes32 _paymentID) external {
(
address _creator,
address[] memory _parties,
,
,
,
,
,
bool _disputed,
,
,
) = arbitrableProxy.getAgreementInfo(_paymentID);
Payment storage payment = payments[_paymentID];
require(_creator != address(0), "The specified payment does not exist.");
require(!payment.executed, "The specified payment has already been executed.");
require(!_disputed, "The specified payment is disputed.");
require(now - payment.createdAt > payment.timeOut, "The specified payment has not timed out yet.");
_parties[1].send(payment.value); // Avoid blocking.
payment.executed = true;
}

/* Public */

/** @dev Executes the ruling on the specified agreement.
* @param _agreementID The ID of the agreement.
* @param _ruling The ruling.
*/
function executeAgreementRuling(bytes32 _agreementID, uint _ruling) public {
super.executeAgreementRuling(_agreementID, _ruling);
(
,
address[] memory _parties,
,
,
,
,
,
,
,
,
) = arbitrableProxy.getAgreementInfo(_agreementID);
(
,
uint[] memory _stake,
,
uint[2][] memory _totalContributedPerSide,
bool[] memory _loserFullyFunded
) = arbitrableProxy.getFeesInfo(_agreementID);
Payment storage payment = payments[_agreementID];
require(!payment.executed, "The specified agreement has already been executed.");

if (_stake.length == 1) { // Failed to fund first round.
// Send the value to whoever paid more.
if (_totalContributedPerSide[0][0] >= _totalContributedPerSide[0][1])
_parties[0].send(payment.value); // Avoid blocking.
else
_parties[1].send(payment.value); // Avoid blocking.
} else { // Failed to fund a later round.
// Respect the ruling unless the losing side funded the appeal and the winning side paid less than expected.
if (
_loserFullyFunded[_loserFullyFunded.length - 1] &&
_totalContributedPerSide[_totalContributedPerSide.length - 1][0] - _stake[_stake.length - 1] > _totalContributedPerSide[_totalContributedPerSide.length - 1][1]
)
_parties[_ruling == 0 ? 1 : 0].send(payment.value); // Avoid blocking.
else
_parties[_ruling].send(payment.value); // Avoid blocking.
}

payment.executed = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -203,29 +203,27 @@ contract MultiPartyInsurableFees is MultiPartyAgreements {
msg.sender.transfer(_reward);
}

/* Public Views */
/* External Views */

/** @dev Gets the info on fees paid for the specified round of the specified agreement.
/** @dev Gets the info on fees paid for the specified agreement.
* @param _agreementID The ID of the agreement.
* @param _round The round.
* @return The info.
*/
function getRoundInfo(
bytes32 _agreementID,
uint _round
) public view returns(
uint ruling,
uint _stake,
uint totalValue,
uint[2] totalContributedPerSide,
bool loserFullyFunded
function getFeesInfo(
bytes32 _agreementID
) external view returns(
uint[] ruling,
uint[] _stake,
uint[] totalValue,
uint[2][] totalContributedPerSide,
bool[] loserFullyFunded
) {
PaidFees storage _paidFees = paidFees[_agreementID];
ruling = _paidFees.ruling[_round];
_stake = _paidFees.stake[_round];
totalValue = _paidFees.totalValue[_round];
totalContributedPerSide = _paidFees.totalContributedPerSide[_round];
loserFullyFunded = _paidFees.loserFullyFunded[_round];
ruling = _paidFees.ruling;
_stake = _paidFees.stake;
totalValue = _paidFees.totalValue;
totalContributedPerSide = _paidFees.totalContributedPerSide;
loserFullyFunded = _paidFees.loserFullyFunded;
}

/** @dev Gets the contributions by the specified contributor in the specified round of the specified agreement.
Expand All @@ -234,7 +232,7 @@ contract MultiPartyInsurableFees is MultiPartyAgreements {
* @param _contributor The address of the contributor.
* @return The contributions.
*/
function getContributions(bytes32 _agreementID, uint _round, address _contributor) public view returns(uint[2] contributions) {
function getContributions(bytes32 _agreementID, uint _round, address _contributor) external view returns(uint[2] contributions) {
contributions = paidFees[_agreementID].contributions[_round][_contributor];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,40 @@ contract ArbitrableProxy {
bytes _extraData,
uint _arbitrationFeesWaitingTime,
Arbitrator _arbitrator) external;

/* External Views */

/** @dev Gets the info on the specified agreement.
* @param _agreementID The ID of the agreement.
* @return The info.
*/
function getAgreementInfo(bytes32 _agreementID) external view returns(
address creator,
address[] parties,
uint numberOfChoices,
bytes extraData,
uint arbitrationFeesWaitingTime,
Arbitrator arbitrator,
uint disputeID,
bool disputed,
bool appealed,
uint ruling,
bool executed);

function getFeesInfo(
bytes32 _agreementID
) external view returns(
uint[] ruling,
uint[] _stake,
uint[] totalValue,
uint[2][] totalContributedPerSide,
bool[] loserFullyFunded);

/** @dev Gets the contributions by the specified contributor in the specified round of the specified agreement.
* @param _agreementID The ID of the agreement.
* @param _round The round.
* @param _contributor The address of the contributor.
* @return The contributions.
*/
function getContributions(bytes32 _agreementID, uint _round, address _contributor) external view returns(uint[2] contributions);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import "./ArbitrableProxyUser.sol";
* @author Enrique Piqueras - <epiquerass@gmail.com>
* @dev Proxy implementation of `MultiPartyInsurableArbitrableAgreementsBase`.
*/
contract MultiPartyInsurableArbitrableAgreementsProxy is MultiPartyInsurableArbitrableAgreementsBase, ArbitrableProxy {
contract MultiPartyInsurableArbitrableAgreementsProxy is ArbitrableProxy, MultiPartyInsurableArbitrableAgreementsBase {
/* Constructor */

/** @dev Constructs the `MultiPartyInsurableArbitrableAgreementsProxy` contract.
Expand Down

0 comments on commit 6df2f6d

Please sign in to comment.