Skip to content

Commit

Permalink
Merge pull request #30 from gnosis/std_market_w_price
Browse files Browse the repository at this point in the history
Adding market with price logger; Integration into Futarchy oracle;
  • Loading branch information
Georgi87 authored Aug 23, 2017
2 parents 059adb7 + 056d8d5 commit 64a5b62
Show file tree
Hide file tree
Showing 14 changed files with 334 additions and 65 deletions.
4 changes: 2 additions & 2 deletions contracts/Markets/Campaign.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ contract Campaign {
* Storage
*/
Event public eventContract;
MarketFactory public marketFactory;
StandardMarketFactory public marketFactory;
MarketMaker public marketMaker;
Market public market;
uint24 public fee;
Expand Down Expand Up @@ -72,7 +72,7 @@ contract Campaign {
/// @param _deadline Campaign deadline
function Campaign(
Event _eventContract,
MarketFactory _marketFactory,
StandardMarketFactory _marketFactory,
MarketMaker _marketMaker,
uint24 _fee,
uint _funding,
Expand Down
6 changes: 3 additions & 3 deletions contracts/Markets/CampaignFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ contract CampaignFactory {
/*
* Events
*/
event CampaignCreation(address indexed creator, Campaign campaign, Event eventContract, MarketFactory marketFactory, MarketMaker marketMaker, uint24 fee, uint funding, uint deadline);
event CampaignCreation(address indexed creator, Campaign campaign, Event eventContract, StandardMarketFactory marketFactory, MarketMaker marketMaker, uint24 fee, uint funding, uint deadline);

/*
* Public functions
Expand All @@ -22,9 +22,9 @@ contract CampaignFactory {
/// @param funding Initial funding for market
/// @param deadline Campaign deadline
/// @return Market contract
function createCampaigns(
function createCampaign(
Event eventContract,
MarketFactory marketFactory,
StandardMarketFactory marketFactory,
MarketMaker marketMaker,
uint24 fee,
uint funding,
Expand Down
19 changes: 0 additions & 19 deletions contracts/Markets/MarketFactory.sol

This file was deleted.

2 changes: 1 addition & 1 deletion contracts/Markets/StandardMarket.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ contract StandardMarket is Market {
/*
* Modifiers
*/
modifier isCreator () {
modifier isCreator() {
// Only creator is allowed to proceed
require(msg.sender == creator);
_;
Expand Down
12 changes: 8 additions & 4 deletions contracts/Markets/StandardMarketFactory.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
pragma solidity 0.4.15;
import "../Markets/MarketFactory.sol";
import "../Markets/StandardMarket.sol";


/// @title Market factory contract - Allows to create market contracts
/// @author Stefan George - <stefan@gnosis.pm>
contract StandardMarketFactory is MarketFactory {
contract StandardMarketFactory {

/*
* Events
*/
event StandardMarketCreation(address indexed creator, Market market, Event eventContract, MarketMaker marketMaker, uint24 fee);

/*
* Public functions
Expand All @@ -17,9 +21,9 @@ contract StandardMarketFactory is MarketFactory {
/// @return Market contract
function createMarket(Event eventContract, MarketMaker marketMaker, uint24 fee)
public
returns (Market market)
returns (StandardMarket market)
{
market = new StandardMarket(msg.sender, eventContract, marketMaker, fee);
MarketCreation(msg.sender, market, eventContract, marketMaker, fee);
StandardMarketCreation(msg.sender, market, eventContract, marketMaker, fee);
}
}
134 changes: 134 additions & 0 deletions contracts/Markets/StandardMarketWithPriceLogger.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
pragma solidity 0.4.15;
import "../Markets/StandardMarket.sol";


contract StandardMarketWithPriceLogger is StandardMarket {

/*
* Constants
*/
uint constant ONE = 0x10000000000000000;
uint8 public constant LONG = 1;

/*
* Storage
*/
uint public startDate;
uint public endDate;
uint public lastTradeDate;
uint public lastTradePrice;
uint public priceIntegral;

/*
* Public functions
*/
/// @dev Constructor validates and sets market properties
/// @param _creator Market creator
/// @param _eventContract Event contract
/// @param _marketMaker Market maker contract
/// @param _fee Market fee
/// @param _startDate Start date for price logging
function StandardMarketWithPriceLogger(address _creator, Event _eventContract, MarketMaker _marketMaker, uint24 _fee, uint _startDate)
public
StandardMarket(_creator, _eventContract, _marketMaker, _fee)
{
require(eventContract.getOutcomeCount() == 2);

if (_startDate == 0)
startDate = now;
else {
// The earliest start date is the market creation date
require(_startDate >= now);
startDate = _startDate;
}

lastTradeDate = startDate;
// initialize lastTradePrice to assuming uniform probabilities of outcomes
lastTradePrice = ONE / 2;
}

/// @dev Allows market creator to close the markets by transferring all remaining outcome tokens to the creator
function close()
public
{
endDate = now;
super.close();
}

/// @dev Allows to buy outcome tokens from market maker
/// @param outcomeTokenIndex Index of the outcome token to buy
/// @param outcomeTokenCount Amount of outcome tokens to buy
/// @param maxCost The maximum cost in collateral tokens to pay for outcome tokens
/// @return Cost in collateral tokens
function buy(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint maxCost)
public
returns (uint cost)
{
logPriceBefore();
cost = super.buy(outcomeTokenIndex, outcomeTokenCount, maxCost);
logPriceAfter();
}

/// @dev Allows to sell outcome tokens to market maker
/// @param outcomeTokenIndex Index of the outcome token to sell
/// @param outcomeTokenCount Amount of outcome tokens to sell
/// @param minProfit The minimum profit in collateral tokens to earn for outcome tokens
/// @return Profit in collateral tokens
function sell(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint minProfit)
public
returns (uint profit)
{
logPriceBefore();
profit = super.sell(outcomeTokenIndex, outcomeTokenCount, minProfit);
logPriceAfter();
}

/// @dev Buys all outcomes, then sells all shares of selected outcome which were bought, keeping
/// shares of all other outcome tokens.
/// @param outcomeTokenIndex Index of the outcome token to short sell
/// @param outcomeTokenCount Amount of outcome tokens to short sell
/// @param minProfit The minimum profit in collateral tokens to earn for short sold outcome tokens
/// @return Cost to short sell outcome in collateral tokens
function shortSell(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint minProfit)
public
returns (uint cost)
{
logPriceBefore();
cost = super.shortSell(outcomeTokenIndex, outcomeTokenCount, minProfit);
logPriceAfter();
}

/// @dev Calculates average price for long tokens based on price integral
/// @return Average price for long tokens over time
function getAvgPrice()
public
returns (uint)
{
if(endDate > 0)
return (priceIntegral + lastTradePrice * (endDate - lastTradeDate)) / (endDate - startDate);
return (priceIntegral + lastTradePrice * (now - lastTradeDate)) / (now - startDate);
}

/*
* Private functions
*/
/// @dev Adds price integral since the last trade to the total price integral
function logPriceBefore()
private
{
if (now >= startDate) {
// Accumulate price integral only if logging has begun
priceIntegral += lastTradePrice * (now - lastTradeDate);
}
}

/// @dev Updates last trade timestamp and price
function logPriceAfter()
private
{
// Refresh lastTradePrice after every transactions as we don't know if
// this will be the last transaction before logging period starts
lastTradePrice = marketMaker.calcMarginalPrice(this, LONG);
lastTradeDate = now;
}
}
30 changes: 30 additions & 0 deletions contracts/Markets/StandardMarketWithPriceLoggerFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
pragma solidity 0.4.15;
import "../Markets/StandardMarketWithPriceLogger.sol";


/// @title Market factory contract - Allows to create market contracts
/// @author Stefan George - <stefan@gnosis.pm>
contract StandardMarketWithPriceLoggerFactory {

/*
* Events
*/
event StandardMarketWithPriceLoggerCreation(address indexed creator, Market market, Event eventContract, MarketMaker marketMaker, uint24 fee, uint startDate);

/*
* Public functions
*/
/// @dev Creates a new market contract
/// @param eventContract Event contract
/// @param marketMaker Market maker contract
/// @param fee Market fee
/// @param startDate Start date for price logging
/// @return Market contract
function createMarket(Event eventContract, MarketMaker marketMaker, uint24 fee, uint startDate)
public
returns (StandardMarketWithPriceLogger market)
{
market = new StandardMarketWithPriceLogger(msg.sender, eventContract, marketMaker, fee, startDate);
StandardMarketWithPriceLoggerCreation(msg.sender, market, eventContract, marketMaker, fee, startDate);
}
}
37 changes: 20 additions & 17 deletions contracts/Oracles/FutarchyOracle.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pragma solidity 0.4.15;
import "../Oracles/Oracle.sol";
import "../Events/EventFactory.sol";
import "../Markets/MarketFactory.sol";
import "../Markets/StandardMarketWithPriceLoggerFactory.sol";


/// @title Futarchy oracle contract - Allows to create an oracle based on market behaviour
Expand All @@ -25,16 +25,16 @@ contract FutarchyOracle is Oracle {
* Storage
*/
address creator;
Market[] public markets;
StandardMarketWithPriceLogger[] public markets;
CategoricalEvent public categoricalEvent;
uint public deadline;
uint public tradingPeriod;
uint public winningMarketIndex;
bool public isSet;

/*
* Modifiers
*/
modifier isCreator () {
modifier isCreator() {
// Only creator is allowed to proceed
require(msg.sender == creator);
_;
Expand All @@ -54,7 +54,8 @@ contract FutarchyOracle is Oracle {
/// @param marketFactory Market factory contract
/// @param marketMaker Market maker contract
/// @param fee Market fee
/// @param _deadline Decision deadline
/// @param _tradingPeriod Trading period before decision can be determined
/// @param startDate Start date for price logging
function FutarchyOracle(
address _creator,
EventFactory eventFactory,
Expand All @@ -63,15 +64,17 @@ contract FutarchyOracle is Oracle {
uint8 outcomeCount,
int lowerBound,
int upperBound,
MarketFactory marketFactory,
StandardMarketWithPriceLoggerFactory marketFactory,
MarketMaker marketMaker,
uint24 fee,
uint _deadline
uint _tradingPeriod,
uint startDate

)
public
{
// Deadline is in the future
require(_deadline > now);
// trading period is at least a second
require(_tradingPeriod > 0);
// Create decision event
categoricalEvent = eventFactory.createCategoricalEvent(collateralToken, this, outcomeCount);
// Create outcome events
Expand All @@ -82,10 +85,10 @@ contract FutarchyOracle is Oracle {
lowerBound,
upperBound
);
markets.push(marketFactory.createMarket(scalarEvent, marketMaker, fee));
markets.push(marketFactory.createMarket(scalarEvent, marketMaker, fee, startDate));
}
creator = _creator;
deadline = _deadline;
tradingPeriod = _tradingPeriod;
}

/// @dev Funds all markets with equal amount of funding
Expand Down Expand Up @@ -130,15 +133,15 @@ contract FutarchyOracle is Oracle {
function setOutcome()
public
{
// Outcome is not set yet and deadline has passed
require(!isSet && deadline <= now);
// Outcome is not set yet and trading period is over
require(!isSet && markets[0].startDate() + tradingPeriod < now);
// Find market with highest marginal price for long outcome tokens
uint highestMarginalPrice = markets[0].marketMaker().calcMarginalPrice(markets[0], LONG);
uint highestAvgPrice = markets[0].getAvgPrice();
uint highestIndex = 0;
for (uint8 i = 1; i < markets.length; i++) {
uint marginalPrice = markets[i].marketMaker().calcMarginalPrice(markets[i], LONG);
if (marginalPrice > highestMarginalPrice) {
highestMarginalPrice = marginalPrice;
uint avgPrice = markets[i].getAvgPrice();
if (avgPrice > highestAvgPrice) {
highestAvgPrice = avgPrice;
highestIndex = i;
}
}
Expand Down
Loading

0 comments on commit 64a5b62

Please sign in to comment.