2018-10-24 12:52:11 +00:00
|
|
|
pragma solidity >=0.0;
|
2017-07-12 13:46:33 +00:00
|
|
|
import "../Tokens/Token.sol";
|
|
|
|
import "../Tokens/OutcomeToken.sol";
|
|
|
|
import "../Oracles/Oracle.sol";
|
|
|
|
|
|
|
|
|
|
|
|
/// @title Event contract - Provide basic functionality required by different event types
|
|
|
|
/// @author Stefan George - <stefan@gnosis.pm>
|
2019-10-23 20:10:12 +00:00
|
|
|
abstract contract Event {
|
2017-07-12 13:46:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Events
|
|
|
|
*/
|
|
|
|
event OutcomeTokenCreation(OutcomeToken outcomeToken, uint8 index);
|
|
|
|
event OutcomeTokenSetIssuance(address indexed buyer, uint collateralTokenCount);
|
|
|
|
event OutcomeTokenSetRevocation(address indexed seller, uint outcomeTokenCount);
|
|
|
|
event OutcomeAssignment(int outcome);
|
|
|
|
event WinningsRedemption(address indexed receiver, uint winnings);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Storage
|
|
|
|
*/
|
|
|
|
Token public collateralToken;
|
|
|
|
Oracle public oracle;
|
|
|
|
bool public isOutcomeSet;
|
|
|
|
int public outcome;
|
|
|
|
OutcomeToken[] public outcomeTokens;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Public functions
|
|
|
|
*/
|
|
|
|
/// @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 outcomeCount Number of event outcomes
|
2018-06-25 13:02:20 +00:00
|
|
|
constructor(Token _collateralToken, Oracle _oracle, uint8 outcomeCount)
|
2017-07-12 13:46:33 +00:00
|
|
|
{
|
|
|
|
// Validate input
|
2018-06-12 09:05:49 +00:00
|
|
|
require(address(_collateralToken) != address(0) && address(_oracle) != address(0) && outcomeCount >= 2);
|
2017-07-12 13:46:33 +00:00
|
|
|
collateralToken = _collateralToken;
|
|
|
|
oracle = _oracle;
|
|
|
|
// Create an outcome token for each outcome
|
|
|
|
for (uint8 i = 0; i < outcomeCount; i++) {
|
|
|
|
OutcomeToken outcomeToken = new OutcomeToken();
|
|
|
|
outcomeTokens.push(outcomeToken);
|
2018-06-27 08:35:38 +00:00
|
|
|
emit OutcomeTokenCreation(outcomeToken, i);
|
2017-07-12 13:46:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @dev Buys equal number of tokens of all outcomes, exchanging collateral tokens and sets of outcome tokens 1:1
|
|
|
|
/// @param collateralTokenCount Number of collateral tokens
|
|
|
|
function buyAllOutcomes(uint collateralTokenCount)
|
|
|
|
public
|
|
|
|
{
|
|
|
|
// Transfer collateral tokens to events contract
|
2018-07-12 18:07:16 +00:00
|
|
|
require(collateralToken.transferFrom(msg.sender, address(this), collateralTokenCount));
|
2017-07-12 13:46:33 +00:00
|
|
|
// Issue new outcome tokens to sender
|
|
|
|
for (uint8 i = 0; i < outcomeTokens.length; i++)
|
|
|
|
outcomeTokens[i].issue(msg.sender, collateralTokenCount);
|
2018-06-27 08:35:38 +00:00
|
|
|
emit OutcomeTokenSetIssuance(msg.sender, collateralTokenCount);
|
2017-07-12 13:46:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// @dev Sells equal number of tokens of all outcomes, exchanging collateral tokens and sets of outcome tokens 1:1
|
|
|
|
/// @param outcomeTokenCount Number of outcome tokens
|
|
|
|
function sellAllOutcomes(uint outcomeTokenCount)
|
|
|
|
public
|
|
|
|
{
|
|
|
|
// Revoke sender's outcome tokens of all outcomes
|
|
|
|
for (uint8 i = 0; i < outcomeTokens.length; i++)
|
|
|
|
outcomeTokens[i].revoke(msg.sender, outcomeTokenCount);
|
|
|
|
// Transfer collateral tokens to sender
|
|
|
|
require(collateralToken.transfer(msg.sender, outcomeTokenCount));
|
2018-06-27 08:35:38 +00:00
|
|
|
emit OutcomeTokenSetRevocation(msg.sender, outcomeTokenCount);
|
2017-07-12 13:46:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// @dev Sets winning event outcome
|
|
|
|
function setOutcome()
|
|
|
|
public
|
|
|
|
{
|
|
|
|
// Winning outcome is not set yet in event contract but in oracle contract
|
|
|
|
require(!isOutcomeSet && oracle.isOutcomeSet());
|
|
|
|
// Set winning outcome
|
|
|
|
outcome = oracle.getOutcome();
|
|
|
|
isOutcomeSet = true;
|
2018-06-27 08:35:38 +00:00
|
|
|
emit OutcomeAssignment(outcome);
|
2017-07-12 13:46:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// @dev Returns outcome count
|
|
|
|
/// @return Outcome count
|
|
|
|
function getOutcomeCount()
|
|
|
|
public
|
2018-07-02 09:14:28 +00:00
|
|
|
view
|
2017-07-12 13:46:33 +00:00
|
|
|
returns (uint8)
|
|
|
|
{
|
|
|
|
return uint8(outcomeTokens.length);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @dev Returns outcome tokens array
|
|
|
|
/// @return Outcome tokens
|
|
|
|
function getOutcomeTokens()
|
|
|
|
public
|
2018-07-02 09:14:28 +00:00
|
|
|
view
|
2018-07-14 21:42:01 +00:00
|
|
|
returns (OutcomeToken[] memory)
|
2017-07-12 13:46:33 +00:00
|
|
|
{
|
|
|
|
return outcomeTokens;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @dev Returns the amount of outcome tokens held by owner
|
2019-10-21 22:05:34 +00:00
|
|
|
/// @return outcomeTokenDistribution Outcome token distribution
|
2017-07-12 13:46:33 +00:00
|
|
|
function getOutcomeTokenDistribution(address owner)
|
|
|
|
public
|
2018-07-02 09:14:28 +00:00
|
|
|
view
|
2018-07-14 21:42:01 +00:00
|
|
|
returns (uint[] memory outcomeTokenDistribution)
|
2017-07-12 13:46:33 +00:00
|
|
|
{
|
|
|
|
outcomeTokenDistribution = new uint[](outcomeTokens.length);
|
|
|
|
for (uint8 i = 0; i < outcomeTokenDistribution.length; i++)
|
|
|
|
outcomeTokenDistribution[i] = outcomeTokens[i].balanceOf(owner);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @dev Calculates and returns event hash
|
|
|
|
/// @return Event hash
|
2019-11-05 17:25:34 +00:00
|
|
|
function getEventHash() virtual public view returns (bytes32);
|
2017-07-12 13:46:33 +00:00
|
|
|
|
|
|
|
/// @dev Exchanges sender's winning outcome tokens for collateral tokens
|
|
|
|
/// @return Sender's winnings
|
2019-11-05 17:25:34 +00:00
|
|
|
function redeemWinnings() virtual public returns (uint);
|
2017-07-12 13:46:33 +00:00
|
|
|
}
|