forked from gnosis/pm-contracts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ScalarEvent.sol
108 lines (98 loc) · 3.68 KB
/
ScalarEvent.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
pragma solidity ^0.4.24;
import "@gnosis.pm/util-contracts/contracts/Proxy.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "../Events/Event.sol";
contract ScalarEventData {
/*
* Constants
*/
uint8 public constant SHORT = 0;
uint8 public constant LONG = 1;
uint24 public constant OUTCOME_RANGE = 1000000;
/*
* Storage
*/
int public lowerBound;
int public upperBound;
}
contract ScalarEventProxy is Proxy, EventData, ScalarEventData {
/// @dev Contract constructor validates and sets basic event properties
/// @param _collateralToken Tokens used as collateral in exchange for outcome tokens
/// @param _oracle Oracle contract used to resolve the event
/// @param _lowerBound Lower bound for event outcome
/// @param _upperBound Lower bound for event outcome
constructor(
address proxied,
address outcomeTokenMasterCopy,
ERC20 _collateralToken,
Oracle _oracle,
int _lowerBound,
int _upperBound
)
Proxy(proxied)
public
{
// Validate input
require(address(_collateralToken) != 0 && address(_oracle) != 0);
collateralToken = _collateralToken;
oracle = _oracle;
// Create an outcome token for each outcome
for (uint8 i = 0; i < 2; i++) {
OutcomeToken outcomeToken = OutcomeToken(new OutcomeTokenProxy(outcomeTokenMasterCopy));
outcomeTokens.push(outcomeToken);
emit OutcomeTokenCreation(outcomeToken, i);
}
// Validate bounds
require(_upperBound > _lowerBound);
lowerBound = _lowerBound;
upperBound = _upperBound;
}
}
/// @title Scalar event contract - Scalar events resolve to a number within a range
/// @author Stefan George - <stefan@gnosis.pm>
contract ScalarEvent is Proxied, Event, ScalarEventData {
using SafeMath for *;
/*
* Public functions
*/
/// @dev Exchanges sender's winning outcome tokens for collateral tokens
/// @return Sender's winnings
function redeemWinnings()
public
returns (uint winnings)
{
// Winning outcome has to be set
require(isOutcomeSet);
// Calculate winnings
uint24 convertedWinningOutcome;
// Outcome is lower than defined lower bound
if (outcome < lowerBound)
convertedWinningOutcome = 0;
// Outcome is higher than defined upper bound
else if (outcome > upperBound)
convertedWinningOutcome = OUTCOME_RANGE;
// Map outcome to outcome range
else
convertedWinningOutcome = uint24(OUTCOME_RANGE * (outcome - lowerBound) / (upperBound - lowerBound));
uint factorShort = OUTCOME_RANGE - convertedWinningOutcome;
uint factorLong = OUTCOME_RANGE - factorShort;
uint shortOutcomeTokenCount = outcomeTokens[SHORT].balanceOf(msg.sender);
uint longOutcomeTokenCount = outcomeTokens[LONG].balanceOf(msg.sender);
winnings = shortOutcomeTokenCount.mul(factorShort).add(longOutcomeTokenCount.mul(factorLong)) / OUTCOME_RANGE;
// Revoke all outcome tokens
outcomeTokens[SHORT].revoke(msg.sender, shortOutcomeTokenCount);
outcomeTokens[LONG].revoke(msg.sender, longOutcomeTokenCount);
// Payout winnings to sender
require(collateralToken.transfer(msg.sender, winnings));
emit WinningsRedemption(msg.sender, winnings);
}
/// @dev Calculates and returns event hash
/// @return Event hash
function getEventHash()
public
view
returns (bytes32)
{
return keccak256(abi.encodePacked(collateralToken, oracle, lowerBound, upperBound));
}
}