Permalink
Browse files

Tie Arbitrator to a single Reality Check address, as suggested by aud…

…itors
  • Loading branch information...
Edmund Edgar
Edmund Edgar committed Apr 6, 2018
1 parent 2fcd6f1 commit a4068686b3edb7df5356b64ac29e9ff38952293e
Showing with 44 additions and 30 deletions.
  1. +25 −13 truffle/contracts/Arbitrator.sol
  2. +19 −17 truffle/contracts/test.py
@@ -5,6 +5,8 @@ import './RealityCheck.sol';

contract Arbitrator is Owned {

RealityCheck public realitycheck;

mapping(bytes32 => uint256) public arbitration_bounties;

uint256 dispute_fee;
@@ -17,10 +19,15 @@ contract Arbitrator is Owned {
uint256 remaining
);

event LogSetRealityCheck(
address realitycheck
);

event LogSetQuestionFee(
uint256 fee
);


event LogSetDisputeFee(
uint256 fee
);
@@ -36,6 +43,15 @@ contract Arbitrator is Owned {
owner = msg.sender;
}

/// @notice Set the Reality Check contract address
/// @param addr The address of the Reality Check contract
function setRealityCheck(address addr)
onlyOwner
public {
realitycheck = RealityCheck(addr);
LogSetRealityCheck(addr);
}

/// @notice Set the default fee
/// @param fee The default fee amount
function setDisputeFee(uint256 fee)
@@ -64,37 +80,34 @@ contract Arbitrator is Owned {
}

/// @notice Set a fee for asking a question with us as the arbitrator
/// @param realitycheck The RealityCheck contract address
/// @param fee The fee amount
/// @dev Default is no fee. Unlike the dispute fee, 0 is an acceptable setting.
/// You could set an impossibly high fee if you want to prevent us being used as arbitrator unless we submit the question.
/// (Submitting the question ourselves is not implemented here.)
/// This fee can be used as a revenue source, an anti-spam measure, or both.
function setQuestionFee(address realitycheck, uint256 fee)
function setQuestionFee(uint256 fee)
onlyOwner
public {
RealityCheck(realitycheck).setQuestionFee(fee);
realitycheck.setQuestionFee(fee);
LogSetQuestionFee(fee);
}

/// @notice Submit the arbitrator's answer to a question.
/// @param realitycheck The RealityCheck contract address
/// @param question_id The question in question
/// @param answer The answer
/// @param answerer The answerer. If arbitration changed the answer, it should be the payer. If not, the old answerer.
function submitAnswerByArbitrator(address realitycheck, bytes32 question_id, bytes32 answer, address answerer)
function submitAnswerByArbitrator(bytes32 question_id, bytes32 answer, address answerer)
onlyOwner
public {
delete arbitration_bounties[question_id];
RealityCheck(realitycheck).submitAnswerByArbitrator(question_id, answer, answerer);
realitycheck.submitAnswerByArbitrator(question_id, answer, answerer);
}

/// @notice Request arbitration, freezing the question until we send submitAnswerByArbitrator
/// @dev The bounty can be paid only in part, in which case the last person to pay will be considered the payer
/// Will trigger an error if the notification fails, eg because the question has already been finalized
/// @param realitycheck The RealityCheck contract address
/// @param question_id The question in question
function requestArbitration(address realitycheck, bytes32 question_id)
function requestArbitration(bytes32 question_id)
external payable returns (bool) {

uint256 arbitration_fee = getDisputeFee(question_id);
@@ -104,11 +117,11 @@ contract Arbitrator is Owned {
uint256 paid = arbitration_bounties[question_id];

if (paid >= arbitration_fee) {
RealityCheck(realitycheck).notifyOfArbitrationRequest(question_id, msg.sender);
realitycheck.notifyOfArbitrationRequest(question_id, msg.sender);
LogRequestArbitration(question_id, msg.value, msg.sender, 0);
return true;
} else {
require(!RealityCheck(realitycheck).isFinalized(question_id));
require(!realitycheck.isFinalized(question_id));
LogRequestArbitration(question_id, msg.value, msg.sender, arbitration_fee - paid);
return false;
}
@@ -128,12 +141,11 @@ contract Arbitrator is Owned {
}

/// @notice Withdraw any accumulated question fees from the specified address into this contract
/// @param realitycheck The address of the Reality Check contract containing the fees
/// @dev Funds can then be liberated from this contract with our withdraw() function
function callWithdraw(address realitycheck)
function callWithdraw()
onlyOwner
public {
RealityCheck(realitycheck).withdraw();
realitycheck.withdraw();
}

}
@@ -80,10 +80,12 @@ def setUp(self):
self.c.mine()
self.rc0 = self.c.contract(self.rc_code, language='solidity', sender=t.k0)

self.arb0.setRealityCheck(self.rc0.address, sender=t.k0, startgas=200000)

self.c.mine()
self.s = self.c.head_state

self.arb0.setQuestionFee(self.rc0.address, 100)
self.arb0.setQuestionFee(100)

self.question_id = self.rc0.askQuestion(
0,
@@ -257,11 +259,11 @@ def test_arbitrator_answering_answered(self):
# The arbitrator cannot submit an answer that has not been requested.
# (If they really want to do this, they can always pay themselves for arbitration.)
with self.assertRaises(TransactionFailed):
self.arb0.submitAnswerByArbitrator(self.rc0.address, self.question_id, to_answer_for_contract(123456), keys.privtoaddr(t.k0), startgas=200000)
self.arb0.submitAnswerByArbitrator(self.question_id, to_answer_for_contract(123456), keys.privtoaddr(t.k0), startgas=200000)

self.assertFalse(self.rc0.isFinalized(self.question_id))

self.assertTrue(self.arb0.requestArbitration(self.rc0.address, self.question_id, value=self.arb0.getDisputeFee(), startgas=200000 ), "Requested arbitration")
self.assertTrue(self.arb0.requestArbitration(self.question_id, value=self.arb0.getDisputeFee(), startgas=200000 ), "Requested arbitration")
question = self.rc0.questions(self.question_id)
#self.assertEqual(question[QINDEX_FINALIZATION_TS], 1, "When arbitration is pending for an answered question, we set the finalization_ts to 1")
self.assertTrue(question[QINDEX_IS_PENDING_ARBITRATION], "When arbitration is pending for an answered question, we set the is_pending_arbitration flag to True")
@@ -272,7 +274,7 @@ def test_arbitrator_answering_answered(self):

self.c.mine()
self.s = self.c.head_state
self.arb0.submitAnswerByArbitrator(self.rc0.address, self.question_id, to_answer_for_contract(123456), keys.privtoaddr(t.k0), startgas=200000)
self.arb0.submitAnswerByArbitrator(self.question_id, to_answer_for_contract(123456), keys.privtoaddr(t.k0), startgas=200000)

self.assertTrue(self.rc0.isFinalized(self.question_id))
self.assertEqual(from_answer_for_contract(self.rc0.getFinalAnswer(self.question_id)), 123456, "Arbitrator submitting final answer calls finalize")
@@ -281,19 +283,19 @@ def test_arbitrator_answering_answered(self):
def test_arbitrator_answering_unanswered(self):

with self.assertRaises(TransactionFailed):
self.arb0.submitAnswerByArbitrator(self.rc0.address, self.question_id, to_answer_for_contract(123456), self.arb0.address, startgas=200000)
self.arb0.submitAnswerByArbitrator(self.question_id, to_answer_for_contract(123456), self.arb0.address, startgas=200000)

self.assertFalse(self.rc0.isFinalized(self.question_id))

self.assertTrue(self.arb0.requestArbitration(self.rc0.address, self.question_id, value=self.arb0.getDisputeFee(), startgas=200000 ), "Requested arbitration")
self.assertTrue(self.arb0.requestArbitration(self.question_id, value=self.arb0.getDisputeFee(), startgas=200000 ), "Requested arbitration")
question = self.rc0.questions(self.question_id)
self.assertTrue(question[QINDEX_IS_PENDING_ARBITRATION], "When arbitration is pending for an answered question, we set the arbitration flag to True")

# You cannot submit the answer unless you are the arbitrator
with self.assertRaises(TransactionFailed):
self.rc0.submitAnswerByArbitrator(self.question_id, to_answer_for_contract(123456), self.arb0.address, startgas=200000)

self.arb0.submitAnswerByArbitrator(self.rc0.address, self.question_id, to_answer_for_contract(123456), self.arb0.address, startgas=200000)
self.arb0.submitAnswerByArbitrator(self.question_id, to_answer_for_contract(123456), self.arb0.address, startgas=200000)

question = self.rc0.questions(self.question_id)
self.assertFalse(question[QINDEX_IS_PENDING_ARBITRATION], "When arbitration is done, we set the arbitration flag to False")
@@ -326,7 +328,7 @@ def submitAnswerReturnUpdatedState(self, st, qid, ans, max_last, bond, sdr, is_c
st['answer'][0] = commitment_id
else:
if is_arbitrator:
self.arb0.submitAnswerByArbitrator(self.rc0.address, qid, to_answer_for_contract(ans), 0, 0, keys.privtoaddr(sdr), startgas=200000)
self.arb0.submitAnswerByArbitrator(qid, to_answer_for_contract(ans), 0, 0, keys.privtoaddr(sdr), startgas=200000)
else:
self.rc0.submitAnswer(qid, to_answer_for_contract(ans), max_last, value=bond, sender=sdr)
st['nonce'].insert(0, nonce)
@@ -365,7 +367,7 @@ def test_set_dispute_fee(self):
# fee of 0 should mean you can never request arbitration
self.arb0.setDisputeFee(0, startgas=200000)
with self.assertRaises(TransactionFailed):
self.arb0.requestArbitration(self.rc0.address, self.question_id, value=self.arb0.getDisputeFee(), startgas=200000)
self.arb0.requestArbitration(self.question_id, value=self.arb0.getDisputeFee(), startgas=200000)

self.arb0.setDisputeFee(123, startgas=200000)
self.assertEqual(self.arb0.getDisputeFee(self.question_id), 123)
@@ -382,15 +384,15 @@ def test_set_dispute_fee(self):

@unittest.skipIf(WORKING_ONLY, "Not under construction")
def test_bond_claim_arbitration_existing_none(self):
self.arb0.requestArbitration(self.rc0.address, self.question_id, value=self.arb0.getDisputeFee(), startgas=200000)
self.arb0.requestArbitration(self.question_id, value=self.arb0.getDisputeFee(), startgas=200000)
st_hash = self.rc0.questions(self.question_id)[QINDEX_HISTORY_HASH]

self.assertEqual(encode_hex(st_hash), "0"*64)

st_addr = keys.privtoaddr(t.k4)
st_bond = 0
st_answer = to_answer_for_contract(1001)
self.arb0.submitAnswerByArbitrator(self.rc0.address, self.question_id, to_answer_for_contract(1001), keys.privtoaddr(t.k4), startgas=200000)
self.arb0.submitAnswerByArbitrator(self.question_id, to_answer_for_contract(1001), keys.privtoaddr(t.k4), startgas=200000)
hh = self.rc0.claimWinnings(self.question_id, [st_hash], [st_addr], [st_bond], [st_answer], startgas=400000)
self.assertEqual(self.rc0.balanceOf(keys.privtoaddr(t.k4)), 1000)
return
@@ -403,13 +405,13 @@ def test_bond_claim_arbitration_existing_final(self):
st = self.submitAnswerReturnUpdatedState( st, self.question_id, 1002, 4, 8, t.k3)
st = self.submitAnswerReturnUpdatedState( st, self.question_id, 1001, 8, 16, t.k4)

self.arb0.requestArbitration(self.rc0.address, self.question_id, value=self.arb0.getDisputeFee(), startgas=200000)
self.arb0.requestArbitration(self.question_id, value=self.arb0.getDisputeFee(), startgas=200000)

st['hash'].insert(0, self.rc0.questions(self.question_id)[QINDEX_HISTORY_HASH])
st['addr'].insert(0, keys.privtoaddr(t.k4))
st['bond'].insert(0, 0)
st['answer'].insert(0, to_answer_for_contract(1001))
self.arb0.submitAnswerByArbitrator(self.rc0.address, self.question_id, to_answer_for_contract(1001), keys.privtoaddr(t.k4), startgas=200000)
self.arb0.submitAnswerByArbitrator(self.question_id, to_answer_for_contract(1001), keys.privtoaddr(t.k4), startgas=200000)

self.rc0.claimWinnings(self.question_id, st['hash'], st['addr'], st['bond'], st['answer'], startgas=400000)
self.assertEqual(self.rc0.balanceOf(keys.privtoaddr(t.k4)), 16+8+4+2+1000)
@@ -545,13 +547,13 @@ def test_bond_claim_arbitration_existing_not_final(self):
st = self.submitAnswerReturnUpdatedState( st, self.question_id, 1002, 4, 8, t.k3)
st = self.submitAnswerReturnUpdatedState( st, self.question_id, 1001, 8, 16, t.k4)

self.arb0.requestArbitration(self.rc0.address, self.question_id, value=self.arb0.getDisputeFee(), startgas=200000)
self.arb0.requestArbitration(self.question_id, value=self.arb0.getDisputeFee(), startgas=200000)

st['hash'].insert(0, self.rc0.questions(self.question_id)[QINDEX_HISTORY_HASH])
st['addr'].insert(0, keys.privtoaddr(t.k3))
st['bond'].insert(0, 0)
st['answer'].insert(0, to_answer_for_contract(1002))
self.arb0.submitAnswerByArbitrator(self.rc0.address, self.question_id, to_answer_for_contract(1002), keys.privtoaddr(t.k3), startgas=200000)
self.arb0.submitAnswerByArbitrator(self.question_id, to_answer_for_contract(1002), keys.privtoaddr(t.k3), startgas=200000)

self.rc0.claimWinnings(self.question_id, st['hash'], st['addr'], st['bond'], st['answer'], startgas=400000)
self.assertEqual(self.rc0.balanceOf(keys.privtoaddr(t.k3)), 16+8+4+2+1000)
@@ -877,7 +879,7 @@ def test_answer_question_gas(self):
def test_question_fee_withdrawal(self):

start_bal = self.rc0.balanceOf(self.arb0.address)
self.arb0.setQuestionFee(self.rc0.address, 321)
self.arb0.setQuestionFee(321)

question_id = self.rc0.askQuestion(
0,
@@ -909,7 +911,7 @@ def test_question_fee_withdrawal(self):
self.c.mine()
self.s = self.c.head_state

self.arb0.callWithdraw(self.rc0.address, sender=t.k0)
self.arb0.callWithdraw(sender=t.k0)
end_arb_bal = self.s.get_balance(self.arb0.address)

self.assertEqual(end_arb_bal - start_arb_bal, 100 + (321*2))

0 comments on commit a406868

Please sign in to comment.