2018-10-24 12:52:11 +00:00
|
|
|
pragma solidity >=0.0;
|
2017-07-12 13:46:33 +00:00
|
|
|
import "../Oracles/Oracle.sol";
|
|
|
|
|
|
|
|
|
|
|
|
/// @title Signed message oracle contract - Allows to set an outcome with a signed message
|
|
|
|
/// @author Stefan George - <stefan@gnosis.pm>
|
|
|
|
contract SignedMessageOracle is Oracle {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Events
|
|
|
|
*/
|
|
|
|
event SignerReplacement(address indexed newSigner);
|
|
|
|
event OutcomeAssignment(int outcome);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Storage
|
|
|
|
*/
|
|
|
|
address public signer;
|
|
|
|
bytes32 public descriptionHash;
|
|
|
|
uint nonce;
|
|
|
|
bool public isSet;
|
|
|
|
int public outcome;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Modifiers
|
|
|
|
*/
|
|
|
|
modifier isSigner () {
|
|
|
|
// Only signer is allowed to proceed
|
|
|
|
require(msg.sender == signer);
|
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Public functions
|
|
|
|
*/
|
|
|
|
/// @dev Constructor sets signer address based on signature
|
|
|
|
/// @param _descriptionHash Hash identifying off chain event description
|
|
|
|
/// @param v Signature parameter
|
|
|
|
/// @param r Signature parameter
|
|
|
|
/// @param s Signature parameter
|
2018-06-25 13:02:20 +00:00
|
|
|
constructor(bytes32 _descriptionHash, uint8 v, bytes32 r, bytes32 s)
|
2017-07-12 13:46:33 +00:00
|
|
|
public
|
|
|
|
{
|
|
|
|
signer = ecrecover(_descriptionHash, v, r, s);
|
|
|
|
descriptionHash = _descriptionHash;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @dev Replaces signer
|
|
|
|
/// @param newSigner New signer
|
|
|
|
/// @param _nonce Unique nonce to prevent replay attacks
|
|
|
|
/// @param v Signature parameter
|
|
|
|
/// @param r Signature parameter
|
|
|
|
/// @param s Signature parameter
|
|
|
|
function replaceSigner(address newSigner, uint _nonce, uint8 v, bytes32 r, bytes32 s)
|
|
|
|
public
|
|
|
|
isSigner
|
|
|
|
{
|
|
|
|
// Result is not set yet and nonce and signer are valid
|
|
|
|
require( !isSet
|
|
|
|
&& _nonce > nonce
|
2018-06-14 10:28:33 +00:00
|
|
|
&& signer == ecrecover(keccak256(abi.encodePacked(descriptionHash, newSigner, _nonce)), v, r, s));
|
2017-07-12 13:46:33 +00:00
|
|
|
nonce = _nonce;
|
|
|
|
signer = newSigner;
|
2018-06-27 08:35:38 +00:00
|
|
|
emit SignerReplacement(newSigner);
|
2017-07-12 13:46:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// @dev Sets outcome based on signed message
|
|
|
|
/// @param _outcome Signed event outcome
|
|
|
|
/// @param v Signature parameter
|
|
|
|
/// @param r Signature parameter
|
|
|
|
/// @param s Signature parameter
|
|
|
|
function setOutcome(int _outcome, uint8 v, bytes32 r, bytes32 s)
|
|
|
|
public
|
|
|
|
{
|
|
|
|
// Result is not set yet and signer is valid
|
|
|
|
require( !isSet
|
2018-06-14 10:28:33 +00:00
|
|
|
&& signer == ecrecover(keccak256(abi.encodePacked(descriptionHash, _outcome)), v, r, s));
|
2017-07-12 13:46:33 +00:00
|
|
|
isSet = true;
|
|
|
|
outcome = _outcome;
|
2018-06-27 08:35:38 +00:00
|
|
|
emit OutcomeAssignment(_outcome);
|
2017-07-12 13:46:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// @dev Returns if winning outcome
|
|
|
|
/// @return Is outcome set?
|
|
|
|
function isOutcomeSet()
|
|
|
|
public
|
2019-09-16 12:33:43 +00:00
|
|
|
override
|
2018-07-02 09:14:28 +00:00
|
|
|
view
|
2017-07-12 13:46:33 +00:00
|
|
|
returns (bool)
|
|
|
|
{
|
|
|
|
return isSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @dev Returns winning outcome
|
|
|
|
/// @return Outcome
|
|
|
|
function getOutcome()
|
|
|
|
public
|
2019-09-16 12:33:43 +00:00
|
|
|
override
|
2018-07-02 09:14:28 +00:00
|
|
|
view
|
2017-07-12 13:46:33 +00:00
|
|
|
returns (int)
|
|
|
|
{
|
|
|
|
return outcome;
|
|
|
|
}
|
|
|
|
}
|