Skip to content

Commit 4f1fba2

Browse files
committed
Child universes may be created manually
1 parent b58d960 commit 4f1fba2

File tree

9 files changed

+53
-36
lines changed

9 files changed

+53
-36
lines changed

source/contracts/reporting/BaseReportingParticipant.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ contract BaseReportingParticipant is Controlled, IReportingParticipant {
3434

3535
function fork() public onlyInGoodTimes returns (bool) {
3636
require(market == market.getUniverse().getForkingMarket());
37-
IUniverse _newUniverse = market.getUniverse().createChildUniverse(payoutDistributionHash);
37+
IUniverse _newUniverse = market.getUniverse().createChildUniverse(payoutNumerators, invalid);
3838
IReputationToken _newReputationToken = _newUniverse.getReputationToken();
3939
redeemForAllFeeWindows();
4040
uint256 _balance = reputationToken.balanceOf(this);

source/contracts/reporting/IReputationToken.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ contract IReputationToken is ITyped, ERC20 {
1414
function trustedFeeWindowTransfer(address _source, address _destination, uint256 _attotokens) public returns (bool);
1515
function trustedUniverseTransfer(address _source, address _destination, uint256 _attotokens) public returns (bool);
1616
function getUniverse() public view returns (IUniverse);
17+
function getTotalMigrated() public view returns (uint256);
1718
function mintForReportingParticipant(uint256 _amountMigrated) public returns (bool);
1819
}

source/contracts/reporting/IUniverse.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ contract IUniverse is ITyped {
1515
function initialize(IUniverse _parentUniverse, bytes32 _parentPayoutDistributionHash) external returns (bool);
1616
function fork() public returns (bool);
1717
function getParentUniverse() public view returns (IUniverse);
18-
function createChildUniverse(bytes32 _parentPayoutDistributionHash) public returns (IUniverse);
18+
function createChildUniverse(uint256[] _parentPayoutNumerators, bool _invalid) public returns (IUniverse);
1919
function getChildUniverse(bytes32 _parentPayoutDistributionHash) public view returns (IUniverse);
2020
function getReputationToken() public view returns (IReputationToken);
2121
function getForkingMarket() public view returns (IMarket);
@@ -40,6 +40,7 @@ contract IUniverse is ITyped {
4040
function getCurrentFeeWindow() public view returns (IFeeWindow);
4141
function getOrCreateFeeWindowBefore(IFeeWindow _feeWindow) public returns (IFeeWindow);
4242
function isParentOf(IUniverse _shadyChild) public view returns (bool);
43+
function updateTentativeWinningChildUniverse(bytes32 _parentPayoutDistributionHash) public returns (bool);
4344
function isContainerForFeeWindow(IFeeWindow _shadyTarget) public view returns (bool);
4445
function isContainerForMarket(IMarket _shadyTarget) public view returns (bool);
4546
function isContainerForReportingParticipant(IReportingParticipant _reportingParticipant) public view returns (bool);

source/contracts/reporting/ReputationToken.sol

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ contract ReputationToken is DelegationTarget, Extractable, ITyped, Initializable
2222
string constant public symbol = "REP";
2323
uint256 constant public decimals = 18;
2424
IUniverse private universe;
25+
uint256 private totalMigrated;
2526

2627
function initialize(IUniverse _universe) public onlyInGoodTimes beforeInitialized returns (bool) {
2728
endInitialization();
@@ -42,12 +43,11 @@ contract ReputationToken is DelegationTarget, Extractable, ITyped, Initializable
4243
IUniverse _parentUniverse = universe.getParentUniverse();
4344
require(ReputationToken(msg.sender) == _parentUniverse.getReputationToken());
4445
mint(_reporter, _attotokens);
45-
// Award a bonus if migration is done before the fork has resolved and check if the fork can be resolved early
46+
totalMigrated += _attotokens;
47+
// Award a bonus if migration is done before the fork has resolved and update the universe tentative winner tracking
4648
if (!_parentUniverse.getForkingMarket().isFinalized()) {
4749
mint(_reporter, _attotokens.div(Reporting.getForkMigrationPercentageBonusDivisor()));
48-
if (supply > _parentUniverse.getForkReputationGoal()) {
49-
_parentUniverse.getForkingMarket().finalizeFork();
50-
}
50+
_parentUniverse.updateTentativeWinningChildUniverse(universe.getParentPayoutDistributionHash());
5151
}
5252
return true;
5353
}
@@ -108,6 +108,10 @@ contract ReputationToken is DelegationTarget, Extractable, ITyped, Initializable
108108
return universe;
109109
}
110110

111+
function getTotalMigrated() public view returns (uint256) {
112+
return totalMigrated;
113+
}
114+
111115
function onTokenTransfer(address _from, address _to, uint256 _value) internal returns (bool) {
112116
controller.getAugur().logReputationTokensTransferred(universe, _from, _to, _value);
113117
return true;

source/contracts/reporting/Universe.sol

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ contract Universe is DelegationTarget, Extractable, ITyped, Initializable, IUniv
2626
bytes32 private parentPayoutDistributionHash;
2727
IReputationToken private reputationToken;
2828
IMarket private forkingMarket;
29+
bytes32 private tentativeWinningChildUniversePayoutDistributionHash;
2930
uint256 private forkEndTime;
3031
uint256 private forkReputationGoal;
3132
mapping(uint256 => IFeeWindow) private feeWindows;
3233
mapping(address => bool) private markets;
33-
IUniverse[] private childUniverses;
34+
mapping(bytes32 => IUniverse) private childUniverses;
3435
uint256 private openInterestInAttoEth;
3536

3637
mapping (address => uint256) private validityBondInAttoeth;
@@ -60,8 +61,6 @@ contract Universe is DelegationTarget, Extractable, ITyped, Initializable, IUniv
6061
} else {
6162
// We're using a hardcoded supply value instead of getting the total REP supply from the token since at launch we will start out with a 0 supply token and users will migrate legacy REP to this token. Since the first fork may occur before all REP migrates we want to count that unmigrated REP too since it may participate in the fork eventually.
6263
forkReputationGoal = Reporting.getInitialREPSupply() / Reporting.getForkRepMigrationVictoryDivisor();
63-
// Account for the bonus for migrating rep that occurs before finalization
64-
forkReputationGoal += forkReputationGoal / Reporting.getForkMigrationPercentageBonusDivisor();
6564
}
6665
controller.getAugur().logUniverseForked();
6766
return true;
@@ -104,13 +103,7 @@ contract Universe is DelegationTarget, Extractable, ITyped, Initializable, IUniv
104103
}
105104

106105
function getChildUniverse(bytes32 _parentPayoutDistributionHash) public view returns (IUniverse) {
107-
for (uint8 i=0; i < childUniverses.length; i++) {
108-
IUniverse _childUniverse = childUniverses[i];
109-
if (_childUniverse.getParentPayoutDistributionHash() == _parentPayoutDistributionHash) {
110-
return _childUniverse;
111-
}
112-
}
113-
return IUniverse(0);
106+
return childUniverses[_parentPayoutDistributionHash];
114107
}
115108

116109
function getFeeWindowId(uint256 _timestamp) public view returns (uint256) {
@@ -164,34 +157,41 @@ contract Universe is DelegationTarget, Extractable, ITyped, Initializable, IUniv
164157
return getOrCreateFeeWindowByTimestamp(_feeWindow.getStartTime() - 2);
165158
}
166159

167-
function createChildUniverse(bytes32 _parentPayoutDistributionHash) public returns (IUniverse) {
168-
IReportingParticipant _reportingParticipant = IReportingParticipant(msg.sender);
169-
require(isContainerForReportingParticipant(_reportingParticipant));
170-
require(_reportingParticipant.getMarket() == forkingMarket);
160+
function createChildUniverse(uint256[] _parentPayoutNumerators, bool _parentInvalid) public returns (IUniverse) {
161+
bytes32 _parentPayoutDistributionHash = forkingMarket.derivePayoutDistributionHash(_parentPayoutNumerators, _parentInvalid);
171162
IUniverse _childUniverse = getChildUniverse(_parentPayoutDistributionHash);
172163
if (_childUniverse == IUniverse(0)) {
173164
_childUniverse = controller.getAugur().createChildUniverse(_parentPayoutDistributionHash);
174-
childUniverses.push(_childUniverse);
165+
childUniverses[_parentPayoutDistributionHash] = _childUniverse;
175166
controller.getAugur().logUniverseCreated(_childUniverse);
176167
}
177168
return _childUniverse;
178169
}
179170

171+
function updateTentativeWinningChildUniverse(bytes32 _parentPayoutDistributionHash) public returns (bool) {
172+
IUniverse _tentativeWinningUniverse = getChildUniverse(tentativeWinningChildUniversePayoutDistributionHash);
173+
IUniverse _updatedUniverse = getChildUniverse(_parentPayoutDistributionHash);
174+
uint256 _currentTentativeWinningChildUniverseRepMigrated = 0;
175+
if (_tentativeWinningUniverse != IUniverse(0)) {
176+
_tentativeWinningUniverse.getReputationToken().getTotalMigrated();
177+
}
178+
uint256 _updatedUniverseRepMigrated = _updatedUniverse.getReputationToken().getTotalMigrated();
179+
if (_updatedUniverseRepMigrated > _currentTentativeWinningChildUniverseRepMigrated) {
180+
tentativeWinningChildUniversePayoutDistributionHash = _parentPayoutDistributionHash;
181+
}
182+
if (_updatedUniverseRepMigrated >= forkReputationGoal) {
183+
forkingMarket.finalizeFork();
184+
}
185+
return true;
186+
}
187+
180188
function getWinningChildUniverse() public view returns (IUniverse) {
181189
require(forkingMarket != IMarket(0));
182-
require(childUniverses.length > 0);
183-
uint256 _winningAmount = 0;
184-
IUniverse _winningUniverse;
185-
for (uint8 i = 0; i < childUniverses.length; i++) {
186-
uint256 _balance = childUniverses[i].getReputationToken().totalSupply();
187-
if (_balance > _winningAmount) {
188-
_winningUniverse = childUniverses[i];
189-
_winningAmount = _balance;
190-
}
191-
}
192-
require(_winningUniverse != IUniverse(0));
190+
require(tentativeWinningChildUniversePayoutDistributionHash != bytes32(0));
191+
IUniverse _tentativeWinningUniverse = getChildUniverse(tentativeWinningChildUniversePayoutDistributionHash);
192+
uint256 _winningAmount = _tentativeWinningUniverse.getReputationToken().getTotalMigrated();
193193
require(_winningAmount >= forkReputationGoal || controller.getTimestamp() > forkEndTime);
194-
return _winningUniverse;
194+
return _tentativeWinningUniverse;
195195
}
196196

197197
function isContainerForFeeWindow(IFeeWindow _shadyFeeWindow) public view returns (bool) {

tests/conftest.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,9 +346,8 @@ def getShareToken(self, market, outcome):
346346
return shareToken
347347

348348
def getOrCreateChildUniverse(self, parentUniverse, market, payoutDistribution):
349-
payoutDistributionHash = market.derivePayoutDistributionHash(payoutDistribution, False)
350349
assert payoutDistributionHash
351-
childUniverseAddress = parentUniverse.getOrCreateChildUniverse(payoutDistributionHash)
350+
childUniverseAddress = parentUniverse.getOrCreateChildUniverse(payoutDistribution, False)
352351
assert childUniverseAddress
353352
childUniverse = ABIContract(self.chain, ContractTranslator(ContractsFixture.signatures['Universe']), childUniverseAddress)
354353
return childUniverse

tests/reporting/test_reporting.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ def test_forking(finalizeByMigration, localFixture, universe, market, categorica
158158
with raises(TransactionFailed, message="We cannot migrate until the fork is finalized"):
159159
categoricalMarket.migrateThroughOneFork()
160160

161+
# confirm that we can manually create a child universe from an outcome no one asserted was true during dispute
162+
numTicks = market.getNumTicks()
163+
childUniverse = universe.createChildUniverse([numTicks/ 4, numTicks * 3 / 4], False)
164+
161165
# finalize the fork
162166
finalizeFork(localFixture, market, universe, finalizeByMigration)
163167

tests/solidity_test_helpers/MockReputationToken.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,8 @@ contract MockReputationToken is DelegationTarget, ITyped, Initializable, MockVar
178178
function mintForReportingParticipant(uint256 _amountMigrated) public returns (bool) {
179179
return true;
180180
}
181+
182+
function getTotalMigrated() public view returns (uint256) {
183+
return 0;
184+
}
181185
}

tests/solidity_test_helpers/MockUniverse.sol

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ contract MockUniverse is Initializable, IUniverse {
391391
return _newMarket;
392392
}
393393

394-
function createChildUniverse(bytes32 _parentPayoutDistributionHash) public returns (IUniverse) {
394+
function createChildUniverse(uint256[] _parentPayoutNumerators, bool _parentInvalid) public returns (IUniverse) {
395395
return IUniverse(0);
396396
}
397397

@@ -426,4 +426,8 @@ contract MockUniverse is Initializable, IUniverse {
426426
function isForking() public view returns (bool) {
427427
return true;
428428
}
429+
430+
function updateTentativeWinningChildUniverse(bytes32 _parentPayoutDistributionHash) public returns (bool) {
431+
return true;
432+
}
429433
}

0 commit comments

Comments
 (0)