dione/eth-contracts/contracts/DioneDispute.sol

84 lines
3.2 KiB
Solidity
Raw Normal View History

pragma solidity ^0.8.0;
2021-02-26 19:53:43 +00:00
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
2021-02-26 19:53:43 +00:00
import "./interfaces/IDioneStaking.sol";
contract DioneDispute {
using SafeMath for uint256;
IDioneStaking public dioneStaking;
struct Dispute {
bytes32 dhash; // id of dispute - keccak256(_miner,_requestId,_timestamp)
uint256 sum; // vote measure (for/against this dispute)
2021-02-26 19:53:43 +00:00
bool finished; // dispute was finished (closed) or not
bool disputeResult; // true - dispute had basis, false - dispute was false
address miner; // the miner against whom the dispute
address disputeInitiator; // the miner who started the dispute
uint256 timestamp; // dispute creation timestamp
address[] voted; // map of miners who vote for/against
2021-02-26 19:53:43 +00:00
}
mapping(bytes32 => Dispute) disputes;
event NewDispute(bytes32 dhash, uint256 requestID, address indexed miner, address indexed disputeInitiator);
2021-02-26 19:53:43 +00:00
event NewVote(bytes32 dhash, address indexed votedMiner);
event DisputeFinished(bytes32 dhash, bool status);
constructor(IDioneStaking _dioneStaking) {
2021-02-26 19:53:43 +00:00
dioneStaking = _dioneStaking;
}
function beginDispute(address miner, uint256 requestID) public {
bytes32 dhash = keccak256(abi.encodePacked(miner, requestID, block.timestamp));
require(disputes[dhash].dhash.length != 0, "dispute already exists");
Dispute storage dispute = disputes[dhash];
dispute.dhash = dhash;
dispute.sum = 0;
dispute.finished = false;
dispute.disputeResult = false;
dispute.miner = miner;
dispute.timestamp = block.timestamp;
dispute.disputeInitiator = msg.sender;
2021-02-26 19:53:43 +00:00
disputes[dhash] = dispute;
emit NewDispute(dhash, requestID, miner, msg.sender);
2021-02-26 19:53:43 +00:00
}
function vote(bytes32 dhash, bool voteStatus) public {
require(disputes[dhash].dhash.length == 0, "dispute doesn't exist");
2021-02-26 19:53:43 +00:00
Dispute storage dispute = disputes[dhash];
require(dispute.finished == false, "dispute already finished");
require(dioneStaking.isMiner(msg.sender), "caller isn't dione miner");
uint256 stake = dioneStaking.minerStake(msg.sender);
2021-02-26 19:53:43 +00:00
if (voteStatus) {
dispute.sum.sub(stake);
} else {
dispute.sum.add(stake);
}
dispute.voted.push(msg.sender);
2021-02-26 19:53:43 +00:00
emit NewVote(dhash, msg.sender);
}
function finishDispute(bytes32 dhash) public {
require(disputes[dhash].dhash.length == 0, "dispute doesn't exist");
2021-02-26 19:53:43 +00:00
Dispute storage dispute = disputes[dhash];
require((block.timestamp - dispute.timestamp) >= 2 hours, "vote window must be two hours");
require(dispute.finished == false, "dispute already finished");
require(dispute.disputeInitiator == msg.sender, "only dispute initiator can call this function");
2021-02-26 19:53:43 +00:00
if (dispute.sum < 0) {
dispute.disputeResult = false;
} else {
dispute.disputeResult = true;
dispute.voted.push(msg.sender);
dioneStaking.slashMiner(dispute.miner, dispute.voted);
2021-02-26 19:53:43 +00:00
}
dispute.finished = true;
2021-02-26 19:53:43 +00:00
emit DisputeFinished(dhash, dispute.disputeResult);
}
}