Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions solidity/contracts/peripherals/Auction.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ contract Auction {
uint256 public auctionStarted;
uint256 public ethAmountToBuy;
bool public finalized;
address immutable owner;
address public owner;

event Participated(address user, uint256 repAmount, uint256 ethAmount, uint256 totalRepPurchased);
event FinalizedAuction(address user, uint256 repAmount, uint256 ethAmount);
event AuctionStarted(uint256 ethAmountToBuy, uint256 repAvailable);

constructor(address _owner) {
function setOwner(address _owner) external {
require(owner == address(0x0), 'owner already set!');
owner = _owner;
}

Expand Down
9 changes: 9 additions & 0 deletions solidity/contracts/peripherals/AuctionFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: UNICENSE
pragma solidity 0.8.30;
import { Auction } from './Auction.sol';

contract AuctionFactory {
function deployAuction(bytes32 salt) external returns (Auction) {
return new Auction{ salt: keccak256(abi.encodePacked(msg.sender, salt)) }();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ contract PriceOracleManagerAndOperatorQueuer {
uint256 public lastSettlementTimestamp;
uint256 public lastPrice; // (REP * PRICE_PRECISION) / ETH;
ReputationToken immutable reputationToken;
ISecurityPool public immutable securityPool;
ISecurityPool public securityPool;
OpenOracle public immutable openOracle;

event PriceReported(uint256 reportId, uint256 price);
Expand All @@ -44,12 +44,16 @@ contract PriceOracleManagerAndOperatorQueuer {
uint256 public previousQueuedOperationId;
mapping(uint256 => QueuedOperation) public queuedOperations;

constructor(OpenOracle _openOracle, ISecurityPool _securityPool, ReputationToken _reputationToken) {
constructor(OpenOracle _openOracle, ReputationToken _reputationToken) {
reputationToken = _reputationToken;
securityPool = _securityPool;
openOracle = _openOracle;
}

function setSecurityPool(ISecurityPool _securityPool) public {
require (address(securityPool) == address(0x0), 'already set!');
securityPool = _securityPool;
}

function setRepEthPrice(uint256 _lastPrice) public {
require(msg.sender == address(securityPool), 'only security pool can set');
lastPrice = _lastPrice;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: UNICENSE
pragma solidity 0.8.30;
import { IShareToken } from './interfaces/IShareToken.sol';
import { ShareToken } from './tokens/ShareToken.sol';
import { ISecurityPool } from './interfaces/ISecurityPool.sol';
import { Zoltar } from '../Zoltar.sol';
import { OpenOracle } from './openOracle/OpenOracle.sol';
import { ReputationToken } from '../ReputationToken.sol';
import { PriceOracleManagerAndOperatorQueuer } from './PriceOracleManagerAndOperatorQueuer.sol';

contract PriceOracleManagerAndOperatorQueuerFactory {
function deployPriceOracleManagerAndOperatorQueuer(OpenOracle _openOracle, ReputationToken _reputationToken, bytes32 salt) external returns (PriceOracleManagerAndOperatorQueuer) {
return new PriceOracleManagerAndOperatorQueuer{ salt: keccak256(abi.encodePacked(msg.sender, salt)) }(_openOracle, _reputationToken);
}
}
45 changes: 25 additions & 20 deletions solidity/contracts/peripherals/SecurityPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity 0.8.30;
import { Auction } from './Auction.sol';
import { Zoltar } from '../Zoltar.sol';
import { ReputationToken } from '../ReputationToken.sol';
import { CompleteSet } from './CompleteSet.sol';
import { IShareToken } from './interfaces/IShareToken.sol';
import { PriceOracleManagerAndOperatorQueuer } from './PriceOracleManagerAndOperatorQueuer.sol';
import { ISecurityPool, SecurityVault, SystemState, QuestionOutcome, ISecurityPoolFactory } from './interfaces/ISecurityPool.sol';
import { OpenOracle } from './openOracle/OpenOracle.sol';
Expand Down Expand Up @@ -38,8 +38,9 @@ contract SecurityPool is ISecurityPool {
uint256 public truthAuctionStarted;
SystemState public systemState;

CompleteSet public immutable completeSet;
IShareToken public immutable shareToken;
Auction public immutable truthAuction;

ReputationToken public repToken;
ISecurityPoolFactory public immutable securityPoolFactory;

Expand All @@ -64,22 +65,22 @@ contract SecurityPool is ISecurityPool {
_;
}

constructor(ISecurityPoolFactory _securityPoolFactory, OpenOracle _openOracle, ISecurityPool _parent, Zoltar _zoltar, uint192 _universeId, uint56 _questionId, uint256 _securityMultiplier) {
constructor(ISecurityPoolFactory _securityPoolFactory, Auction _truthAuction, PriceOracleManagerAndOperatorQueuer _priceOracleManagerAndOperatorQueuer, IShareToken _shareToken, OpenOracle _openOracle, ISecurityPool _parent, Zoltar _zoltar, uint192 _universeId, uint56 _questionId, uint256 _securityMultiplier) {
universeId = _universeId;
securityPoolFactory = _securityPoolFactory;
questionId = _questionId;
securityMultiplier = _securityMultiplier;
zoltar = _zoltar;
parent = _parent;
openOracle = _openOracle;
truthAuction = _truthAuction;
priceOracleManagerAndOperatorQueuer = _priceOracleManagerAndOperatorQueuer;
if (address(parent) == address(0x0)) { // origin universe never does truthAuction
systemState = SystemState.Operational;
} else {
systemState = SystemState.ForkMigration;
truthAuction = new Auction{ salt: bytes32(uint256(0x1)) }(address(this));
}
// todo, we can probably do these smarter so that we don't need migration
completeSet = new CompleteSet{ salt: bytes32(uint256(0x1)) }(address(this));
shareToken = _shareToken;
}

function setStartingParams(uint256 _currentRetentionRate, uint256 _repEthPrice, uint256 _completeSetCollateralAmount) public {
Expand All @@ -88,7 +89,6 @@ contract SecurityPool is ISecurityPool {
currentRetentionRate = _currentRetentionRate;
completeSetCollateralAmount = _completeSetCollateralAmount;
(repToken,,) = zoltar.universes(universeId);
priceOracleManagerAndOperatorQueuer = new PriceOracleManagerAndOperatorQueuer{ salt: bytes32(uint256(0x1)) }(openOracle, this, repToken);
priceOracleManagerAndOperatorQueuer.setRepEthPrice(_repEthPrice);
}

Expand Down Expand Up @@ -231,8 +231,9 @@ contract SecurityPool is ISecurityPool {
require(systemState == SystemState.Operational, 'system is not Operational'); //todo, we want to be able to create complete sets in the children right away, figure accounting out
updateCollateralAmount();
require(securityBondAllowance - completeSetCollateralAmount >= msg.value, 'no capacity to create that many sets');
uint256 amountToMint = completeSet.totalSupply() == completeSetCollateralAmount ? msg.value : msg.value * completeSet.totalSupply() / completeSetCollateralAmount;
completeSet.mint(msg.sender, amountToMint);
uint256 totalSupply = shareToken.totalSupplyForUniverse(universeId);
uint256 amountToMint = totalSupply == completeSetCollateralAmount ? msg.value : msg.value * totalSupply / completeSetCollateralAmount; // todo this is wrong
shareToken.mintCompleteSets(universeId, msg.sender, amountToMint);
completeSetCollateralAmount += msg.value;
updateRetentionRate();
}
Expand All @@ -241,20 +242,25 @@ contract SecurityPool is ISecurityPool {
require(systemState == SystemState.Operational, 'system is not Operational'); // todo, we want to allow people to exit, but for accounting purposes that is difficult but maybe there's a way?
updateCollateralAmount();
// takes in complete set and releases security bond and eth
uint256 ethValue = amount * completeSetCollateralAmount / completeSet.totalSupply();
completeSet.burn(msg.sender, amount);
uint256 totalSupply = shareToken.totalSupplyForUniverse(universeId);
uint256 ethValue = amount * completeSetCollateralAmount / totalSupply; // this is wrong
shareToken.burnCompleteSets(universeId, msg.sender, amount);
completeSetCollateralAmount -= ethValue;
updateRetentionRate();
(bool sent, ) = payable(msg.sender).call{value: ethValue}('');
(bool sent, ) = payable(msg.sender).call{ value: ethValue }('');
require(sent, 'Failed to send Ether');
}

/*
function redeemShare() isOperational public {
require(zoltar.isFinalized(universeId, questionId), 'Question has not finalized!');
//convertes yes,no or invalid share to 1 eth each, depending on market outcome
function redeemShares() isOperational external {
Zoltar.Outcome outcome = zoltar.finalizeQuestion(universeId, questionId);
require(outcome != Zoltar.Outcome.None, 'Question has not finalized!');
uint256 tokenId = shareToken.getTokenId(universeId, outcome);
uint256 amount = shareToken.burnTokenId(tokenId, msg.sender);
uint256 totalSupply = shareToken.totalSupplyForUniverse(universeId);
uint256 ethValue = amount * completeSetCollateralAmount / totalSupply; // this is wrong
(bool sent, ) = payable(msg.sender).call{ value: ethValue }('');
require(sent, 'Failed to send Ether');
}
*/

////////////////////////////////////////
// FORKING (migrate vault (oi+rep), truth truthAuction)
Expand All @@ -263,7 +269,6 @@ contract SecurityPool is ISecurityPool {
(,, uint256 forkTime) = zoltar.universes(universeId);
require(forkTime > 0, 'Zoltar needs to have forked before Security Pool can do so');
require(systemState == SystemState.Operational, 'System needs to be operational to trigger fork');
require(securityPoolForkTriggeredTimestamp == 0, 'fork already triggered');
require(!zoltar.isFinalized(universeId, questionId), 'question has been finalized already');
systemState = SystemState.PoolForked;
securityPoolForkTriggeredTimestamp = block.timestamp;
Expand All @@ -285,7 +290,8 @@ contract SecurityPool is ISecurityPool {
if (address(children[uint8(outcome)]) == address(0x0)) {
// first vault migrater creates new pool and transfers all REP to it
uint192 childUniverseId = (universeId << 2) + uint192(outcome) + 1;
children[uint8(outcome)] = securityPoolFactory.deploySecurityPool(openOracle, this, zoltar, childUniverseId, questionId, securityMultiplier, currentRetentionRate, priceOracleManagerAndOperatorQueuer.lastPrice(), 0);
children[uint8(outcome)] = securityPoolFactory.deployChildSecurityPool(shareToken, childUniverseId, questionId, securityMultiplier, currentRetentionRate, priceOracleManagerAndOperatorQueuer.lastPrice(), 0);
shareToken.authorize(children[uint8(outcome)]);
ReputationToken childReputationToken = children[uint8(outcome)].repToken();
childReputationToken.transfer(address(children[uint8(outcome)]), childReputationToken.balanceOf(address(this)));
}
Expand Down Expand Up @@ -321,7 +327,6 @@ contract SecurityPool is ISecurityPool {
function startTruthAuction() public {
require(systemState == SystemState.ForkMigration, 'System needs to be in migration');
require(block.timestamp > securityPoolForkTriggeredTimestamp + SecurityPoolUtils.MIGRATION_TIME, 'migration time needs to pass first');
require(truthAuctionStarted == 0, 'Auction already started');
systemState = SystemState.ForkTruthAuction;
truthAuctionStarted = block.timestamp;
parent.updateCollateralAmount();
Expand Down
63 changes: 58 additions & 5 deletions solidity/contracts/peripherals/SecurityPoolFactory.sol
Original file line number Diff line number Diff line change
@@ -1,15 +1,68 @@
// SPDX-License-Identifier: UNICENSE
pragma solidity 0.8.30;
import { IShareToken } from './interfaces/IShareToken.sol';
import { SecurityPool } from './SecurityPool.sol';
import { ISecurityPool, ISecurityPoolFactory } from './interfaces/ISecurityPool.sol';
import { OpenOracle } from './openOracle/OpenOracle.sol';
import { Zoltar } from '../Zoltar.sol';
import { ShareTokenFactory } from './ShareTokenFactory.sol';
import { AuctionFactory } from './AuctionFactory.sol';
import { Auction } from './Auction.sol';
import { ShareToken } from './tokens/ShareToken.sol';
import { PriceOracleManagerAndOperatorQueuerFactory } from './PriceOracleManagerAndOperatorQueuerFactory.sol';
import { PriceOracleManagerAndOperatorQueuer } from './PriceOracleManagerAndOperatorQueuer.sol';
import { ReputationToken } from '../ReputationToken.sol';

contract SecurityPoolFactory is ISecurityPoolFactory {
event DeploySecurityPool(ISecurityPool securityPool, OpenOracle openOracle, ISecurityPool parent, Zoltar zoltar, uint192 universeId, uint56 questionId, uint256 securityMultiplier, uint256 currentRetentionRate, uint256 startingRepEthPrice, uint256 completeSetCollateralAmount);
function deploySecurityPool(OpenOracle openOracle, ISecurityPool parent, Zoltar zoltar, uint192 universeId, uint56 questionId, uint256 securityMultiplier, uint256 currentRetentionRate, uint256 startingRepEthPrice, uint256 completeSetCollateralAmount) external returns (ISecurityPool securityPoolAddress) {
securityPoolAddress = new SecurityPool{salt: bytes32(uint256(0x1))}(this, openOracle, parent, zoltar, universeId, questionId, securityMultiplier);
securityPoolAddress.setStartingParams(currentRetentionRate, startingRepEthPrice, completeSetCollateralAmount);
emit DeploySecurityPool(securityPoolAddress, openOracle, parent, zoltar, universeId, questionId, securityMultiplier, currentRetentionRate, startingRepEthPrice, completeSetCollateralAmount);
ShareTokenFactory shareTokenFactory;
AuctionFactory auctionFactory;
PriceOracleManagerAndOperatorQueuerFactory priceOracleManagerAndOperatorQueuerFactory;
Zoltar zoltar;
OpenOracle openOracle;

event DeploySecurityPool(ISecurityPool securityPool, Auction truthAuction, PriceOracleManagerAndOperatorQueuer priceOracleManagerAndOperatorQueuer, IShareToken shareToken, ISecurityPool parent, uint192 universeId, uint56 questionId, uint256 securityMultiplier, uint256 currentRetentionRate, uint256 startingRepEthPrice, uint256 completeSetCollateralAmount);

constructor(OpenOracle _openOracle, Zoltar _zoltar, ShareTokenFactory _shareTokenFactory, AuctionFactory _auctionFactory, PriceOracleManagerAndOperatorQueuerFactory _priceOracleManagerAndOperatorQueuerFactory) {
shareTokenFactory = _shareTokenFactory;
auctionFactory = _auctionFactory;
priceOracleManagerAndOperatorQueuerFactory = _priceOracleManagerAndOperatorQueuerFactory;
zoltar = _zoltar;
openOracle = _openOracle;
}

function deployChildSecurityPool(IShareToken shareToken, uint192 universeId, uint56 questionId, uint256 securityMultiplier, uint256 currentRetentionRate, uint256 startingRepEthPrice, uint256 completeSetCollateralAmount) external returns (ISecurityPool securityPool) {
ISecurityPool parent = ISecurityPool(payable(msg.sender));
bytes32 securityPoolSalt = keccak256(abi.encodePacked(parent, universeId, questionId, securityMultiplier));
(ReputationToken reputationToken,,) = zoltar.universes(universeId);
PriceOracleManagerAndOperatorQueuer priceOracleManagerAndOperatorQueuer = priceOracleManagerAndOperatorQueuerFactory.deployPriceOracleManagerAndOperatorQueuer(openOracle, reputationToken, securityPoolSalt);

Auction truthAuction = auctionFactory.deployAuction(securityPoolSalt);

securityPool = new SecurityPool{ salt: bytes32(uint256(0x0)) }(this, truthAuction, priceOracleManagerAndOperatorQueuer, shareToken, openOracle, parent, zoltar, universeId, questionId, securityMultiplier);

priceOracleManagerAndOperatorQueuer.setSecurityPool(securityPool);
securityPool.setStartingParams(currentRetentionRate, startingRepEthPrice, completeSetCollateralAmount);

truthAuction.setOwner(address(securityPool));
emit DeploySecurityPool(securityPool, truthAuction, priceOracleManagerAndOperatorQueuer, shareToken, parent, universeId, questionId, securityMultiplier, currentRetentionRate, startingRepEthPrice, completeSetCollateralAmount);
}

function deployOriginSecurityPool(uint192 universeId, uint56 questionId, uint256 securityMultiplier, uint256 currentRetentionRate, uint256 startingRepEthPrice, uint256 completeSetCollateralAmount) external returns (ISecurityPool securityPool) {
bytes32 securityPoolSalt = keccak256(abi.encodePacked(address(0x0), universeId, questionId, securityMultiplier));
(ReputationToken reputationToken,,) = zoltar.universes(universeId);
PriceOracleManagerAndOperatorQueuer priceOracleManagerAndOperatorQueuer = priceOracleManagerAndOperatorQueuerFactory.deployPriceOracleManagerAndOperatorQueuer(openOracle, reputationToken, securityPoolSalt);

// sharetoken has different salt as sharetoken address does not change in forks
bytes32 shareTokenSalt = keccak256(abi.encodePacked(securityMultiplier));
IShareToken shareToken = shareTokenFactory.deployShareToken(questionId, shareTokenSalt);

securityPool = new SecurityPool{ salt: bytes32(uint256(0x0)) }(this, Auction(address(0x0)), priceOracleManagerAndOperatorQueuer, shareToken, openOracle, ISecurityPool(payable(0x0)), zoltar, universeId, questionId, securityMultiplier);

priceOracleManagerAndOperatorQueuer.setSecurityPool(securityPool);
securityPool.setStartingParams(currentRetentionRate, startingRepEthPrice, completeSetCollateralAmount);

shareToken.authorize(securityPool);

emit DeploySecurityPool(securityPool, Auction(address(0x0)), priceOracleManagerAndOperatorQueuer, shareToken, ISecurityPool(payable(0x0)), universeId, questionId, securityMultiplier, currentRetentionRate, startingRepEthPrice, completeSetCollateralAmount);
}
}
18 changes: 18 additions & 0 deletions solidity/contracts/peripherals/ShareTokenFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: UNICENSE
pragma solidity 0.8.30;
import { IShareToken } from './interfaces/IShareToken.sol';
import { ShareToken } from './tokens/ShareToken.sol';
import { ISecurityPool } from './interfaces/ISecurityPool.sol';
import { Zoltar } from '../Zoltar.sol';

contract ShareTokenFactory {
Zoltar zoltar;

constructor(Zoltar _zoltar) {
zoltar = _zoltar;
}

function deployShareToken(uint56 questionId, bytes32 salt) external returns (IShareToken shareToken) {
return new ShareToken{ salt: salt }(msg.sender, zoltar, questionId);
}
}
Loading