diff options
Diffstat (limited to 'test/compilationTests/gnosis/Events')
-rw-r--r-- | test/compilationTests/gnosis/Events/CategoricalEvent.sol | 53 | ||||
-rw-r--r-- | test/compilationTests/gnosis/Events/Event.sol | 128 | ||||
-rw-r--r-- | test/compilationTests/gnosis/Events/EventFactory.sol | 79 | ||||
-rw-r--r-- | test/compilationTests/gnosis/Events/ScalarEvent.sol | 87 |
4 files changed, 347 insertions, 0 deletions
diff --git a/test/compilationTests/gnosis/Events/CategoricalEvent.sol b/test/compilationTests/gnosis/Events/CategoricalEvent.sol new file mode 100644 index 00000000..fbd1d744 --- /dev/null +++ b/test/compilationTests/gnosis/Events/CategoricalEvent.sol @@ -0,0 +1,53 @@ +pragma solidity ^0.4.11; +import "../Events/Event.sol"; + + +/// @title Categorical event contract - Categorical events resolve to an outcome from a set of outcomes +/// @author Stefan George - <stefan@gnosis.pm> +contract CategoricalEvent is Event { + + /* + * 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 + function CategoricalEvent( + Token _collateralToken, + Oracle _oracle, + uint8 outcomeCount + ) + public + Event(_collateralToken, _oracle, outcomeCount) + { + + } + + /// @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 + winnings = outcomeTokens[uint(outcome)].balanceOf(msg.sender); + // Revoke tokens from winning outcome + outcomeTokens[uint(outcome)].revoke(msg.sender, winnings); + // Payout winnings + require(collateralToken.transfer(msg.sender, winnings)); + WinningsRedemption(msg.sender, winnings); + } + + /// @dev Calculates and returns event hash + /// @return Event hash + function getEventHash() + public + constant + returns (bytes32) + { + return keccak256(collateralToken, oracle, outcomeTokens.length); + } +} diff --git a/test/compilationTests/gnosis/Events/Event.sol b/test/compilationTests/gnosis/Events/Event.sol new file mode 100644 index 00000000..9aa257c4 --- /dev/null +++ b/test/compilationTests/gnosis/Events/Event.sol @@ -0,0 +1,128 @@ +pragma solidity ^0.4.11; +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> +contract Event { + + /* + * 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 + function Event(Token _collateralToken, Oracle _oracle, uint8 outcomeCount) + public + { + // Validate input + require(address(_collateralToken) != 0 && address(_oracle) != 0 && outcomeCount >= 2); + 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); + OutcomeTokenCreation(outcomeToken, i); + } + } + + /// @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 + require(collateralToken.transferFrom(msg.sender, this, collateralTokenCount)); + // Issue new outcome tokens to sender + for (uint8 i = 0; i < outcomeTokens.length; i++) + outcomeTokens[i].issue(msg.sender, collateralTokenCount); + OutcomeTokenSetIssuance(msg.sender, collateralTokenCount); + } + + /// @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)); + OutcomeTokenSetRevocation(msg.sender, outcomeTokenCount); + } + + /// @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; + OutcomeAssignment(outcome); + } + + /// @dev Returns outcome count + /// @return Outcome count + function getOutcomeCount() + public + constant + returns (uint8) + { + return uint8(outcomeTokens.length); + } + + /// @dev Returns outcome tokens array + /// @return Outcome tokens + function getOutcomeTokens() + public + constant + returns (OutcomeToken[]) + { + return outcomeTokens; + } + + /// @dev Returns the amount of outcome tokens held by owner + /// @return Outcome token distribution + function getOutcomeTokenDistribution(address owner) + public + constant + returns (uint[] outcomeTokenDistribution) + { + 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 + function getEventHash() public constant returns (bytes32); + + /// @dev Exchanges sender's winning outcome tokens for collateral tokens + /// @return Sender's winnings + function redeemWinnings() public returns (uint); +} diff --git a/test/compilationTests/gnosis/Events/EventFactory.sol b/test/compilationTests/gnosis/Events/EventFactory.sol new file mode 100644 index 00000000..dfb1a579 --- /dev/null +++ b/test/compilationTests/gnosis/Events/EventFactory.sol @@ -0,0 +1,79 @@ +pragma solidity ^0.4.11; +import "../Events/CategoricalEvent.sol"; +import "../Events/ScalarEvent.sol"; + + +/// @title Event factory contract - Allows creation of categorical and scalar events +/// @author Stefan George - <stefan@gnosis.pm> +contract EventFactory { + + /* + * Events + */ + event CategoricalEventCreation(address indexed creator, CategoricalEvent categoricalEvent, Token collateralToken, Oracle oracle, uint8 outcomeCount); + event ScalarEventCreation(address indexed creator, ScalarEvent scalarEvent, Token collateralToken, Oracle oracle, int lowerBound, int upperBound); + + /* + * Storage + */ + mapping (bytes32 => CategoricalEvent) public categoricalEvents; + mapping (bytes32 => ScalarEvent) public scalarEvents; + + /* + * Public functions + */ + /// @dev Creates a new categorical event and adds it to the event mapping + /// @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 + /// @return Event contract + function createCategoricalEvent( + Token collateralToken, + Oracle oracle, + uint8 outcomeCount + ) + public + returns (CategoricalEvent eventContract) + { + bytes32 eventHash = keccak256(collateralToken, oracle, outcomeCount); + // Event should not exist yet + require(address(categoricalEvents[eventHash]) == 0); + // Create event + eventContract = new CategoricalEvent( + collateralToken, + oracle, + outcomeCount + ); + categoricalEvents[eventHash] = eventContract; + CategoricalEventCreation(msg.sender, eventContract, collateralToken, oracle, outcomeCount); + } + + /// @dev Creates a new scalar event and adds it to the event mapping + /// @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 + /// @return Event contract + function createScalarEvent( + Token collateralToken, + Oracle oracle, + int lowerBound, + int upperBound + ) + public + returns (ScalarEvent eventContract) + { + bytes32 eventHash = keccak256(collateralToken, oracle, lowerBound, upperBound); + // Event should not exist yet + require(address(scalarEvents[eventHash]) == 0); + // Create event + eventContract = new ScalarEvent( + collateralToken, + oracle, + lowerBound, + upperBound + ); + scalarEvents[eventHash] = eventContract; + ScalarEventCreation(msg.sender, eventContract, collateralToken, oracle, lowerBound, upperBound); + } +} diff --git a/test/compilationTests/gnosis/Events/ScalarEvent.sol b/test/compilationTests/gnosis/Events/ScalarEvent.sol new file mode 100644 index 00000000..2e5718ef --- /dev/null +++ b/test/compilationTests/gnosis/Events/ScalarEvent.sol @@ -0,0 +1,87 @@ +pragma solidity ^0.4.11; +import "../Events/Event.sol"; + + +/// @title Scalar event contract - Scalar events resolve to a number within a range +/// @author Stefan George - <stefan@gnosis.pm> +contract ScalarEvent is Event { + using Math for *; + + /* + * Constants + */ + uint8 public constant SHORT = 0; + uint8 public constant LONG = 1; + uint24 public constant OUTCOME_RANGE = 1000000; + + /* + * Storage + */ + int public lowerBound; + int public upperBound; + + /* + * 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 _lowerBound Lower bound for event outcome + /// @param _upperBound Lower bound for event outcome + function ScalarEvent( + Token _collateralToken, + Oracle _oracle, + int _lowerBound, + int _upperBound + ) + public + Event(_collateralToken, _oracle, 2) + { + // Validate bounds + require(_upperBound > _lowerBound); + lowerBound = _lowerBound; + upperBound = _upperBound; + } + + /// @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)); + WinningsRedemption(msg.sender, winnings); + } + + /// @dev Calculates and returns event hash + /// @return Event hash + function getEventHash() + public + constant + returns (bytes32) + { + return keccak256(collateralToken, oracle, lowerBound, upperBound); + } +} |