Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

9Lives

You probably want to read the guide as a developer!

9lives is the most customisable and advanced prediction market in the web3 ecosystem, with an orderbook and AMM feature. We can support teams interested in releasing prediction markets themselves using 9lives, including hosting the graph for you. If you're interested in this, contact us at this link!


9Lives is an Arbitrum Stylus smart contract implemented with a simple factory/pair pattern. A factory takes a list of outcomes, and creates a variable number of contracts with a minimal viable proxy pointing to share ERC20s, and a trading contract. It either supports the Dynamic Pari-Mutuel Market (DPM) model to solve liquidity issues in orderbooks, or a Constant Product Market Maker model to be totally separate.

To get started with the contract entrypoint, src/lib.rs contains the matching of features to deploy different contract facets. Testing is done with a mixture of property and mutation testing and a bespoke testing environment for ERC20 accounting and more.

Inventors create campaigns (the prediction markets) by locking up "incentive" amounts, and by picking the type of oracle they want to use. Any fees earned in the campaign are sent to the Inventor, which provides incentive to create markets. Markets must be created with a hard deadline and a Beauty Contest or a Infrastructure Market, or with a Contract Interaction type of outcome. The Inventor must communicate to the Factory which oracle they would like to use, and provide the hash of the string that must be used to determine the outcome. This will then set the correct behaviour.

flowchart TD
    Trader --> |Locks up incentive amount, sets parameters| Factory
    Factory --> |Sets start, end, description, if infra market oracle chosen| Infra[Infra market]
    Factory --> |Deploys contract. Sets parameters| Trading
    Factory --> |Configures Longtail pool| Longtail
    Factory --> |Deploys ERC20 assets for each outcome| ERC20s
    Trading --> |Disables Longtail once trading is done| Factory
    ERC20s --> |Burns and mints supply| Trading
    Infra --> |Tells Trading who won| Trading

Infra Markets are prediction markets where Staked ARB is locked up as LARB, which is used to predict the outcome of another prediction market with a commit and reveal scheme. These markets exist in an optimistic state where anyone can "call" the outcome, before being challenged with a "whinge", which begins the process of a commit and reveal system. Following this, amounts can be claimed with a slashing process based on amounts staked.

Oracle State oracles are very simple comparatively, as presumably the associated Trading contract was configured to allow early activation, so all a caller must do is activate the associated Oracle State contract. These could communicate with LayerZero to pull information from another chain, and the contract will simply check the result of the message. If it's not activated by the date that's given, then it defaults to a "DEFAULT" clause that could be "no" if a user were to try to estimate the price of something.


Diagram of the system

Roadmap

  • UX improvements (shares are more visible, smart account behaviour)
  • Mainnet is supported as well. Mainnet has disclosure that funds are locked up until the election is over.
  • Achievements and portfolio page is supported. Some socialfi elements.
    1. Users can choose their favourite achievements to display in a minified form next to their Meow Domain.
    2. Meow domains is supported in the UI.
  • Collect payoff from the campaign ending in the frontend.
  • Custom fee collection and pool configuration supported (use beauty contest with fixed date, many outcomes if they want)
  • Anyone can create pools. Custom display of pools a la Ebay customisation.
    1. A fixed fee is sent to creator of when shares are created.
    2. Behind the scenes deferring to the AMM model if more than two outcomes.
    3. Customise the UI of the frontpage for the info
    4. Stack ranking is done for automated updating of frontpage
    5. Campaign report functionality. Images are screened automatically for bad content with CSAM
    6. API to update campaign by the original sender
    7. Custom embed when sharing URL
  • Prediction market DAO. Token launch

Building contracts

make build

Updating docs (after editing markdown files)

forge doc -b

Testing

Testing must be done with no trading or contract feature enabled. Testing is only possible on the local environment, or with end to end tests with an Arbitrum node.

./tests.sh

Interrogation of the deployment in the end to end testing library could be done using the build.rs use of environment.lst, which could be in turn read with a fresh deploy (and a clean artifacts directory):

sort $(find target -name environment.lst) | uniq

You could clear the recorded environment variables the same way with a test harness:

rm $(find target -name environment.lst)

You could use this to test the code by making a debug build, which includes more information about reverts, then simulate your calldata against it using stylus-interpreter, making debugging a breeze.

Errors

The error table lives in ERRORS.md.

Deployments

Superposition mainnet

Deployment nameDeployment address
Proxy admin0x6221A9c005F6e47EB398fD867784CacfDcFFF4E7
Factory 1 implementation0x3302ac14ad6b38baf789571395cc3a54f0f65e52
Factory 2 implementation0x928b627add9c2a3578b5c178423724f4d20202ed
Lockup implementation0x99596b476d5e16e4a30bd4858dd289a763671294
Optimistic infra predict impl0xf94aeb587d332d0e7f2f1e2c87ffea1385ff0505
Trading DPM mint impl0x7b203ff48f76b163bed86b5f2cb66ce6a46d62d4
Trading DPM extras impl0x81eebeda7eb9f68c9a825c619f5e0d13a117e5f6
Trading DPM price impl0x8fc31d39edec596e8089b313920c05642e86d549
Trading DPM quotes impl0x7439ec52bd28c21f59b07a7a12a09c1f7feac7cf
Trading AMM mint impl0x2314c906ebd852a0be249ce49b98ee804078b05e
Trading AMM extras impl0x59c9660f835c1c1c5387a48b9fe8cf7d49020a64
Trading AMM price impl0x7ff05c8bac0bce55e1519015a4a86fe2b244df88
Trading AMM quotes impl0x09e99d6c0e57c2cdb715daf1dc66b98e43514fc3
Share implementation0x3e27e934344bf490457231Cb8F0c0eda7d60C362
Lockup token implementation0x70143C674A23a43Ad487D33c4035Ba1D012ac598
Infrastructure market impl0x863642e21a45e824c4f6347a5757e5dcacae11c1
Infrastructure market proxy0xc4451d8477cd6b92bfa0d3e2662ce0507a8e10b9
Lockup proxy0x20d2360706086ec9814d15a52ad2d2aec2c43caa
Lockup token proxy0x14c35ba87e8b490761f492382c9249867b82aaf4
Factory proxy0x7dfe1fa7760131140cfc48b3ea99719203d8f00b
Helper factory0x2965aF7dD96D550d63be1577feC27ae26d2C46F7
LensesV10x051648539bC4a1C247030EABCBC29cfD1887cd83
Beauty contest implementation0x3421264e413489b1e69ae84ace8c33c6cb7809ff
Beauty contest proxy0x15f4A8a0b8cD0343fAe5a7FC736cD9e0D7bE4d5C
Sarp AI Resolver0x9d73847f1edc930d2a2ee801aeadb4c4567f18e1
Helper factory0x6e95B1fcca9aBb2D94213AE3ccFCaf5BB8406E6B
Buy helper20xEBBfeAcbbD331466512A362BEa782e1f7CB45b57
SARP Signaller0xD608CeF1D7C84feaA0E1520C7a6BC4798cFC1455
Extras beacon proxy factory0x6c1cf52961C567965AFCf495B7af7eCC81411598

Superposition testnet

Deployment nameDeployment address
Proxy admin0xfeb6034fc7df27df18a3a6bad5fb94c0d3dcb6d5
Factory 1 implementation0x9e16b693e71d0be52da2158ac6dd2c3b75fbadf0
Factory 2 implementation0xaca4f34b884969605e7922f44748b5c5a7fb2246
Lockup implementation0x9733dd5d7e1b42f39b4227e4b0b0e17ff440b3c2
Optimistic infra predict impl0xe2175ab2ef7aa29ec61657e505e641a5ff509b72
Trading DPM mint impl0x11a4b84a7d0979e906c8eaba7c16579a3bf48bf5
Trading DPM extras impl0xbd03aff1a558d0806eed2e6e6af48453daf4de40
Trading DPM quotes impl0xccf0aed8c4157cfbc41ad0cd78b23c6fd637271e
Trading DPM price impl0x3c3363a60cf654c84915495f2efdd8dd4c3439af
Trading AMM mint impl0x76c1127f1aa1b4f8b33e6137051df91c50d6eee6
Trading AMM extras impl0xbf5776e6231d511af57a87141adc1217a695f58b
Trading AMM quotes impl0x70a9500293622ff935aa9f65818b80fdbfd9157e
Trading AMM price impl0x4b78c4f0ebeaa1ba42e0d48e7f0cd3c53e1796b9
Share implementation0xC876Fc7ddd41ae072a8898445f83bBfcC903c195
Lockup token implementation0xD813030d171026B42bd9D29aE44b3a5a600cFFf7
Infrastructure market proxy0x1b508fb73912eb306f4ca29cab096c75074ceee4
Lockup proxy0x397420c66164632937a19768174ee7e21c0df3a2
Lockup token proxy0xc9ca48f56454be7ce44b929506b32b61c0c8f6d9
Factory proxy0x48b9cf07bb9dedc7eb33868693b63b28b253f282
Helper factory0x6E0fc15eFc574e17DC181753fdD5852A1c963D97
LensesV10x61F92c803177c1060Ef7B360bD631d857B1545B9
Beauty contest implementation0x40e652ce259d6de7dd4058ce5c255a44785fc4e7
Beauty contest proxy0xc3d76a0b0ca758648b56e2535712f4a9316cb709
Sarp AI Resolver0x0000000000000000000000000000000000000000
Buy helper20x491286b009F19300ac45ed5571e012F125AB9B9d
SARP Signaller0x2137B4C506f0d7eF2A562B02Be9110a4a3A93bC9

IERC20

Git Source

Functions

transferFrom

function transferFrom(address sender, address recipient, uint256 value) external;

approve

function approve(address recipient, uint256 amount) external;

balanceOf

function balanceOf(address spender) external view returns (uint256);

transfer

function transfer(address spender, uint256 amount) external;

DPMOld

Git Source

Functions

mintPermitE90275AB

function mintPermitE90275AB(bytes8, uint256, address, uint256, uint8, bytes32, bytes32) external returns (uint256);

BuyHelper2

Git Source

State Variables

FACTORY

INineLivesFactory immutable FACTORY;

LONGTAIL

ILongtail immutable LONGTAIL;

FUSDC

IERC20 immutable FUSDC;

WETH

IWETH10 immutable WETH;

Functions

constructor

constructor(INineLivesFactory _factory, ILongtail _longtail, address _fusdc, IWETH10 _weth);

mint

Mint some shares at the trading id and outcome given, using Longtail to make a swap to fUSDC from the asset given.

function mint(
    address _tradingAddr,
    address _asset,
    bytes8 _outcome,
    uint256 _minShareOut,
    uint256 _amount,
    address _referrer
) external payable returns (uint256);

burn

function burn(
    address _tradingAddr,
    bytes8 _outcome,
    uint256 _minFusdc,
    uint256 _maxShareOut,
    uint256 _minShareOut,
    address _referrer
) external returns (uint256, uint256);

InfraMarket

Git Source

Functions

ctor

function ctor(address admin, address emergency, ILockup lockup, address lockedArbToken, INineLivesFactory factoryAddr)
    external;

Lockup

Git Source

Functions

ctor

function ctor(address tokenImpl, address infraMarket, address operator) external;

Factory

Git Source

Functions

ctor

function ctor(
    address shareImpl,
    address tradingDpmExtrasImpl,
    address tradingDpmMintImpl,
    address tradingDpmQuotesImpl,
    address tradingDpmPriceImpl,
    address tradingAMMExtrasImpl,
    address tradingAMMMintImpl,
    address tradingAmmQuotesImpl,
    address tradingAmmPriceImpl,
    address infraMarketOracle,
    address operator
) external;

DeployArgs

Git Source

struct DeployArgs {
    address admin;
    address emergencyCouncil;
    address lockupTokenImpl;
    address shareImpl;
    address factory1Impl;
    address factory2Impl;
    address infraMarketImpl;
    address lockupImpl;
    address tradingDpmExtrasImpl;
    address tradingDpmMintImpl;
    address tradingDpmQuotesImpl;
    address tradingDpmPriceImpl;
    address tradingAmmExtrasImpl;
    address tradingAmmMintImpl;
    address tradingAmmQuotesImpl;
    address tradingAmmPriceImpl;
    address beautyContestImpl;
}

DeployHelper

Git Source

Functions

constructor

constructor(DeployArgs memory _a);

Events

FactoryDeployed

event FactoryDeployed(address indexed addr);

InfraMarketDeployed

event InfraMarketDeployed(address indexed addr);

LockupDeployed

event LockupDeployed(address indexed addr);

BeautyContestDeployed

event BeautyContestDeployed(address indexed addr);

ExtrasBeacon

Git Source

State Variables

OWNER

address immutable OWNER;

defaultFacet

address public defaultFacet;

facet

mapping(uint8 => address) public facet;

Functions

constructor

constructor(address _owner, address _default);

impl

function impl(bytes8 _sel) external view returns (address);

upgradeDefault

function upgradeDefault(address _new) external;

upgrade

function upgrade(uint8 _facet, address _new) external;

ExtrasBeaconFactory

Git Source

Functions

deploy

function deploy(address _owner, address _default) external returns (address beacon, address proxy);

ExtrasBeaconProxy

Git Source

State Variables

BEACON

ExtrasBeacon immutable BEACON;

Functions

constructor

constructor(ExtrasBeacon _b);

fallback

fallback() external;

IERC20Permit

Git Source

Functions

permit

function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
    external;

approve

function approve(address spender, uint256 amount) external;

transferFrom

function transferFrom(address owner, address spender, uint256 amount) external;

CreateArgs

Git Source

struct CreateArgs {
    address oracle;
    FactoryOutcome[] outcomes;
    uint64 timeEnding;
    bytes32 documentation;
    address feeRecipient;
    uint64 feeCreator;
    uint64 feeLp;
    uint64 feeMinter;
    uint64 feeReferrer;
    uint256 seedLiquidity;
}

HelperFactory

Git Source

HelperFactory that assists in deploying different amounts, it does not take any fees currently to reflect the new AMM model.

State Variables

FUSDC

IERC20Permit immutable FUSDC;

FACTORY

INineLivesFactory immutable FACTORY;

INFRA_MARKET

address public immutable INFRA_MARKET;

BEAUTY_CONTEST

address public immutable BEAUTY_CONTEST;

SARP_AI

address public immutable SARP_AI;

Functions

constructor

constructor(
    IERC20Permit _fusdc,
    INineLivesFactory _factory,
    address _infraMarket,
    address _beautyContest,
    address _sarpAi
);

create

Create a new campaign, ignoring the CreateArgs oracle argument.

function create(address _oracle, CreateArgs calldata _a) internal returns (address);

createWithBeautyContest

function createWithBeautyContest(CreateArgs calldata _a) public returns (address tradingAddr);

createWithAI

function createWithAI(CreateArgs calldata _a) public returns (address tradingAddr);

createWithCustom

It doesn't make sense to use this. It's better to do the setup work yourself with the factory, this is left for convinience reasons. It transfers some fUSDC to the contract for setup.

function createWithCustom(CreateArgs calldata _a) public returns (address tradingAddr);

Constants

Git Source

INCENTIVE_AMT_MODERATION

uint256 constant INCENTIVE_AMT_MODERATION = 1e6;

INCENTIVE_INFRA_MARKET

uint256 constant INCENTIVE_INFRA_MARKET = 2200000;

IDecidable

Git Source

Functions

decide

Decide an outcome. Only callable by the oracle!

function decide(bytes8 outcome) external;

Parameters

NameTypeDescription
outcomebytes8to set as the winner.

escape

Escape an indeterminate/inconclusive campaign, where an associated contract needs to do something.

function escape() external;

IEvents

Git Source

Events

LockupTokenProxyDeployed

event LockupTokenProxyDeployed(address indexed token);

NewTrading2

event NewTrading2(bytes32 indexed identifier, address indexed addr, address indexed oracle, uint8 backend);

OutcomeCreated

event OutcomeCreated(bytes32 indexed tradingIdentifier, bytes32 indexed erc20Identifier, address indexed erc20Addr);

ClaimedDAOFunds

event ClaimedDAOFunds(address indexed recipient, uint256 indexed amount);

OutcomeDecided

event OutcomeDecided(bytes8 indexed identifier, address indexed oracle);

SharesMinted

event SharesMinted(
    bytes8 indexed identifier,
    uint256 indexed shareAmount,
    address indexed spender,
    address recipient,
    uint256 fusdcSpent
);

SharesBurned

event SharesBurned(
    bytes8 indexed identifier,
    uint256 indexed shareAmount,
    address indexed spender,
    address recipient,
    uint256 fusdcReturned
);

PayoffActivated

event PayoffActivated(
    bytes8 indexed identifier,
    uint256 indexed sharesSpent,
    address indexed spender,
    address recipient,
    uint256 fusdcReceived
);

DeadlineExtension

event DeadlineExtension(uint64 indexed timeBefore, uint64 indexed timeAfter);

LiquidityAdded

event LiquidityAdded(
    address indexed sender, uint256 indexed fusdcAmt, address indexed recipient, uint256 liquidityShares
);

LiquidityRemoved

event LiquidityRemoved(uint256 indexed fusdcAmt, address indexed recipient, uint256 indexed liquidityAmt);

LiquidityClaimed

event LiquidityClaimed(address indexed recipient, uint256 indexed fusdcAmt);

LPFeesClaimed

event LPFeesClaimed(
    address indexed sender, address indexed recipient, uint256 indexed feesEarned, uint256 senderLiquidityShares
);

AddressFeesClaimed

event AddressFeesClaimed(address indexed recipient, uint256 indexed amount);

ReferrerEarnedFees

event ReferrerEarnedFees(address indexed referrer, uint256 indexed fees, uint256 indexed volume);

TimeExtension

event TimeExtension(uint256 indexed newDeadline);

InfraMarketEnabled

event InfraMarketEnabled(bool indexed status);

MarketCreated2

event MarketCreated2(
    address indexed incentiveSender,
    address indexed tradingAddr,
    bytes32 indexed desc,
    uint64 launchTs,
    uint64 callDeadline
);

CallMade

event CallMade(address indexed tradingAddr, bytes8 indexed winner, address indexed incentiveRecipient);

InfraMarketClosed

event InfraMarketClosed(address indexed incentiveRecipient, address indexed tradingAddr, bytes8 indexed winner);

DAOMoneyDistributed

event DAOMoneyDistributed(uint256 indexed amount, address indexed recipient);

Committed

event Committed(address indexed trading, address indexed predictor, bytes32 indexed commitment);

CommitmentRevealed

event CommitmentRevealed(
    address indexed trading, address indexed revealer, bytes8 indexed outcome, address caller, uint256 bal
);

Whinged

event Whinged(address indexed trading, bytes8 indexed preferredOutcome, address indexed whinger);

CampaignEscaped

CampaignEscaped, because a campaign is in an indeterminate state! The DAO may be needed to step in.

event CampaignEscaped(address indexed tradingAddr);

InfraMarketUpdated

event InfraMarketUpdated(address indexed old, address indexed new_);

Declared

Declare was called on a market in the infra market.

event Declared(address indexed trading, bytes8 indexed winningOutcome, address indexed feeRecipient);

LockupEnabled

event LockupEnabled(bool indexed status);

LockedUp

event LockedUp(uint256 indexed amount, address indexed recipient);

Withdrew

event Withdrew(uint256 indexed amount, address indexed recipient);

Slashed

event Slashed(address indexed victim, address indexed recipient, uint256 indexed slashedAmount);

Frozen

event Frozen(address indexed victim, uint64 indexed until);

Requested

Outstanding ticket requested by a user for SARP to resolve a market.

event Requested(address indexed trading, uint256 indexed ticket);

Concluded

A request from a submitter was appropriate and resulted in a non-indeterminate state. Refund the investor.

event Concluded(uint256 indexed ticket, bytes32 indexed justification);

IInfraMarket

Git Source

Functions

ctor

function ctor(address operator, address emergencyCouncil, address lockup, address lockedArbToken, address factory)
    external;

register

Register this campaign, taking a small stipend for management from the creator in the form of $3 fUSDC. Factory caller only.

function register(address trading, bytes32 desc, uint64 launchTs, uint64 callDeadlineTs) external returns (uint256);

Parameters

NameTypeDescription
tradingaddressaddress to configure this
descbytes32of the contract to commit as info for users. Should be info for a oracle.
launchTsuint64to use as the timestamp to begin this infra market. Could be the conclusion date.
callDeadlineTsuint64

call

Call the outcome, changing the state to allow a user to disagree with it with the whinge function. Takes a $2 fUSDC bond.

function call(address tradingAddr, bytes8 winner, address incentiveRecipient) external returns (uint256);

Parameters

NameTypeDescription
tradingAddraddressto call for.
winnerbytes8to indicate is the preferred outcome by this user.
incentiveRecipientaddressto send future incentive amounts, and the refund for the bond to.

whinge

Whinge the outcome, indicating that the sender disagrees with the call decision that was made. This is only possible during a two day window. A $7 fUSDC must be taken from the user.

function whinge(address tradingAddr, bytes8 preferredOutcome, address bondRecipient) external returns (uint256);

Parameters

NameTypeDescription
tradingAddraddressto use for the disagreement that's taking place.
preferredOutcomebytes8to use as the outcome that the whinger disagrees is the best.
bondRecipientaddressto send the bond that's refunded back to.

predict

Make a commitment as to what the preferred outcome should be, now that there's been calling and whinging. The voting power comes from the lockup contract, which takes ARB and locks it up for an amount of time that this trading should close.

function predict(address tradingAddr, bytes32 commit) external;

Parameters

NameTypeDescription
tradingAddraddressto use as the trading address to make commitments for.
commitbytes32to use as the commitment for what the outcome should be.

curOutcomeVestedArb

Get the amount of vested ARB in a specific outcome produced by reveals up until now.

function curOutcomeVestedArb(address trading, bytes8 outcome) external view returns (uint256);

Parameters

NameTypeDescription
tradingaddresscontract this is for.
outcomebytes8that we want to know.

epochNumber

Get the current epoch number for the trading contract given.

function epochNumber(address trading) external view returns (uint256 epochNo);

Parameters

NameTypeDescription
tradingaddressto check.

whingerPreferredWinner

Get the preferred whinger of the infra market given.

function whingerPreferredWinner(address trading) external view returns (bytes8);

Parameters

NameTypeDescription
tradingaddresscontract to get the amount for.

callerPreferredOutcome

Get the caller preferred outcome of the infra market given.

function callerPreferredOutcome(address trading) external view returns (bytes8);

Parameters

NameTypeDescription
tradingaddresscontract to get the amount for.

reveal

Reveal a previously made commitment. Should be done in the revealing period (two days after the first whinge, for two days).

function reveal(address tradingAddr, address committerAddr, bytes8 outcome, uint256 seed) external;

Parameters

NameTypeDescription
tradingAddraddressto use as the place for the commitments to be tracked.
committerAddraddressto use as the address of the user making commitments.
outcomebytes8to state the previously made commitment was for.
seeduint256to use as the random nonce for the reveal.

sweep

Sweep money from a bettor who bet incorrectly, or someone who neglected to reveal their commitment, who is assumed to be betting that the system is in an indeterminate state.

function sweep(address tradingAddr, uint256 epochNo, address victim, address feeRecipientAddr)
    external
    returns (uint256 yieldForFeeRecipient);

Parameters

NameTypeDescription
tradingAddraddressto use as the trading address for the campaign.
epochNouint256to use as the epoch number to take funds from.
victimaddressto claim funds from.
feeRecipientAddraddressto send the small amount taken from the victim to (1%).

capture

Capture amounts from the prize pool. Can only be done once, so be careful!

function capture(address tradingAddr, uint256 epochNo, address feeRecipient)
    external
    returns (uint256 yieldForFeeRecipient);

Parameters

NameTypeDescription
tradingAddraddressto capture amounts from.
epochNouint256to collect amounts from the pot from.
feeRecipientaddressto send incentive amounts to.

close

Close this campaign if it's been in a state where anyone can whinge for some time, two days since someone whinged and no-one had whinged.

function close(address tradingAddr, address feeRecipient) external;

Parameters

NameTypeDescription
tradingAddraddressthis market is for.
feeRecipientaddressto send the incentive for closing to.

escape

Escape a trading market that has gone over the limit. This calls the escape function in the trading contract to indicate something has gone wrong. This should only be callable if the contract is in the state for calling past the deadline.

function escape(address tradingAddr) external;

Parameters

NameTypeDescription
tradingAddraddressto escape.

winner

Winner that was declared for this infra market, if there is one.

function winner(address tradingAddr) external view returns (bytes8 winnerId);

status

Status of this trading contract's oracle.

function status(address tradingAddr) external view returns (InfraMarketState currentState, uint64 secsRemaining);

startTs

Starting timestamp of the campaign.

function startTs(address trading) external view returns (uint64);

endTs

Ending timestamp of the campaign.

function endTs(address trading) external view returns (uint64);

declare

Declare a winner, by providing the outcomes that were in use, along with a fee recipient to collect the fee for providing this correct calldata to.

function declare(address tradingAddr, bytes8[] calldata outcomes, address feeRecipient) external returns (uint256);

Parameters

NameTypeDescription
tradingAddraddressto use as the trading address for the campaign.
outcomesbytes8[]to use as the outcomes that were in use.
feeRecipientaddressto send the incentive for declaring to.

enableContract

Enable or disable the contract.

function enableContract(bool status) external returns (bool);

Parameters

NameTypeDescription
statusboolto set the contract to.

ILockup

Git Source

Functions

lockup

Lockup ARB to receive LARB.

function lockup(uint256 amount, address recipient) external returns (uint256);

Parameters

NameTypeDescription
amountuint256to lock up.
recipientaddressto send the Locked ARB to.

Returns

NameTypeDescription
<none>uint256the amount of LARB sent to the recipient.

tokenAddr

Token address of LARB.

function tokenAddr() external view returns (address);

lockedUntil

Get the until locked time timestamp.

function lockedUntil(address spender) external view returns (uint64 timestamp);

Parameters

NameTypeDescription
spenderaddressto get the locked until for.

withdraw

Withdraw some LARB to ARB.

function withdraw(uint256 amount, address recipient) external returns (uint256);

Parameters

NameTypeDescription
amountuint256to withdraw.
recipientaddressto send the returned amounts to.

Returns

NameTypeDescription
<none>uint256the amount that was sent back.

slash

Slash a user's entire position portfolio on request. only usable by InfraMarket. This can be called repeatedly safely without context. When this is used the user's amount before they started to lose funds is tracked to be drawn down.

function slash(address victim, uint256 amount, address recipient) external returns (uint256);

Parameters

NameTypeDescription
victimaddressto take money from.
amountuint256to take from the victim.
recipientaddressto send the slashed amounts to.

Returns

NameTypeDescription
<none>uint256amount taken from the victim.

freeze

freeze a user's position to prevent it from being taken until after this deadline. If the amount is already set, then we use the latest value. The infra market is responsible for a correct interaction here.

function freeze(address spender, uint64 until) external;

updateInfraMarket

function updateInfraMarket(address addr) external;

ILongtail

Git Source

Functions

createPool653F395E

function createPool653F395E(address pool, uint256 price, uint32 fee) external;

enablePool579DA658

function enablePool579DA658(address pool, bool enabled) external;

quote72E2ADE7

function quote72E2ADE7(address pool, bool zeroForOne, int256 amount, uint256 priceLimitX96) external;

swapIn32502CA71

function swapIn32502CA71(address _token, uint256 _amount, uint256 _minOut) external returns (int256, int256);

FactoryOutcome

Git Source

struct FactoryOutcome {
    bytes8 identifier;
    uint256 sqrtPrice;
    string name;
}

INineLivesFactory

Git Source

Functions

newTrading320E32E9

set up new trading contract, seeding the initial amounts

function newTrading320E32E9(
    FactoryOutcome[] memory outcomes,
    address oracle,
    uint64 timeStart,
    uint64 timeEnding,
    bytes32 documentation,
    address feeRecipient,
    uint64 feeCreator,
    uint64 feeLp,
    uint64 feeMinter,
    uint64 feeReferrer
) external returns (address tradingAddr);

Parameters

NameTypeDescription
outcomesFactoryOutcome[]to set up as the default
oracleaddressto use as the provider. If set to 0, then a beauty contest is taking place, and when an oracle resolves it checks its own invested state to determine the winner. If set to the address of the infra market oracle as set up during the initialisation of the proxy contract, then an infrastructure market is taking place. If set to anything else, then a contract interaction is assumed being active (or, an AI resolver, depending on the circumstances). If the infrastructure market was chosen, then the code calls the Infrastructure Market to create a new market there with its own creation time.
timeStartuint64to begin this contract at. This should be in the future.
timeEndinguint64to end this contract at. This should be in the future.
documentationbytes32keccak'd hash of the information that makes up the description for infrastructure markets. This is sent out there.
feeRecipientaddressto send fees earned from the creator commission to.
feeCreatoruint64pct to take as fees for the creator given.
feeLpuint64pct to take as fees for LPs who use the add/remove liquidity features.
feeMinteruint64pct to take as fees for users using the mint function.
feeReferreruint64

Returns

NameTypeDescription
tradingAddraddressaddress of the newly created Trading contract deployment.

isModerationFeeEnabled

is the current fee that's taken for moderation reasons active?

function isModerationFeeEnabled() external view returns (bool);

getOwner

gets the owner address from the trading contract address

function getOwner(address addr) external view returns (address);

Parameters

NameTypeDescription
addraddressis trading address to get the owner

getBackend

function getBackend(address addr) external view returns (uint8);

getTradingAddr

function getTradingAddr(bytes32 id) external view returns (address);

shareImpl

function shareImpl() external pure returns (address);

dpmTradingHash

return the keccak256 hash of the trading contract in DPM form.

function dpmTradingHash() external view returns (bytes32);

ammTradingHash

return the keccak256 hash of the trading contract in AMM form.

function ammTradingHash() external view returns (bytes32);

erc20Hash

return the keccak256 hash of the ERC20

function erc20Hash() external view returns (bytes32);

CtorArgs

Git Source

struct CtorArgs {
    bytes8[] outcomes;
    address oracle;
    uint64 timeStart;
    uint64 timeEnding;
    address feeRecipient;
    address shareImpl;
    bool shouldBufferTime;
    uint64 feeCreator;
    uint64 feeMinter;
    uint64 feeLp;
    uint64 feeReferrer;
}

Properties

NameTypeDescription
outcomesbytes8[]to use to use as betting outcomes in this contract.
oracleaddressto use as the resolver for this contract.
timeStartuint64to begin this contract by.
timeEndinguint64to end this contract by.
feeRecipientaddressto send fees earned from trading.
shareImpladdress
shouldBufferTimeboolto extend time by 3 hours for every purchase within a 3 hour window. If this is enabled, the contract will enforce purchases to exceed $10 if they are taking place within 3 hours of the contract's scheduled end time.
feeCreatoruint64to take as the default fee from every mint for the creator of this contract.
feeMinteruint64to take as the fee that we give to minters.
feeLpuint64to take as a fee for the market makers who used the add/remove features.
feeReferreruint64to take and distribute to a referrer for a allocation.

INineLivesTrading

Git Source

Functions

ctor

ctor to set the values for this contract.

function ctor(CtorArgs calldata ctorArgs) external;

Parameters

NameTypeDescription
ctorArgsCtorArgsto use during creation of the setup.

oracle

oracle that's in use in this trading contract.

function oracle() external view returns (address);

mint8A059B6E

Mint some shares in exchange for fUSDC. Optionally branches to permit or a classic approval based on the deadline argument (if set to 0, assumes approval)

function mint8A059B6E(bytes8 outcome, uint256 value, address referrer, address recipient) external returns (uint256);

burn854CC96E

Burn some shares by inverting the AMM function using the fUSDC amount, or the shares, depending on the shouldEstimateShares argument. Returns the burned shares, and the fusdc returned.

function burn854CC96E(
    bytes8 outcome,
    uint256 amount,
    bool shouldEstimateShares,
    uint256 minShares,
    address referrer,
    address recipient
) external returns (uint256 burnedShares, uint256 fusdcReturned);

quoteC0E17FC7

Quote function for testing the amount that could be minted.

function quoteC0E17FC7(bytes8 outcome, uint256 fusdcValue) external returns (uint256 purchased, uint256 fees);

Parameters

NameTypeDescription
outcomebytes8to test for
fusdcValueuint256to test spending for

estimateBurnE9B09A17

function estimateBurnE9B09A17(bytes8 outcome, uint256 shareAmount) external returns (uint256);

rescue276DD9AB

function rescue276DD9AB(address recipient) external returns (uint256);

claimLiquidity9C391F85

function claimLiquidity9C391F85(address recipient) external;

claimLpFees66980F36

function claimLpFees66980F36(address recipient) external;

addLiquidityA975D995

function addLiquidityA975D995(uint256 liquidity, address recipient) external returns (uint256 userLiquidity);

removeLiquidity3C857A15

function removeLiquidity3C857A15(uint256 liquidity, address recipient)
    external
    returns (uint256 fusdcAmount, uint256 lpFeesEarned);

claimAddressFeesB302CF6D

Claim fees owed to a specific address, perhaps after they've been doing referrals.

function claimAddressFeesB302CF6D(address recipient) external returns (uint256);

Parameters

NameTypeDescription
recipientaddressto send the rewards to.

priceA827ED27

Get the price of an outcome in fUSDC.

function priceA827ED27(bytes8 outcome) external returns (uint256);

Parameters

NameTypeDescription
outcomebytes8to test for

shutdown

Shutdown this contract by disabling associated pools. Compensates callers of this function by distributing them a small amount of token for doing so. This can only be called when the contract has exceeded its deadline.

function shutdown() external returns (uint256);

decide

Decide an outcome. Only callable by the oracle!

function decide(bytes8 outcome) external;

Parameters

NameTypeDescription
outcomebytes8to set as the winner.

payoffCB6F2565

Collect the payoff if holding winning shares!

function payoffCB6F2565(bytes8 outcomeId, uint256 amount, address recipient) external returns (uint256);

Parameters

NameTypeDescription
outcomeIdbytes8to collect the payoff for.
amountuint256of share to use for receiving the payoff.
recipientaddressto send the winnings to.

details

Details that're available for this outcome.

function details(bytes8 outcomeId)
    external
    view
    returns (uint256 shares, uint256 invested, uint256 globalInvested, bytes8 winner);

Parameters

NameTypeDescription
outcomeIdbytes8to get the details for

escape

function escape() external;

isDpm

is this trading contract running the DPM?

function isDpm() external view returns (bool);

globalShares

global shares minted.

function globalShares() external view returns (uint256);

invested

Invested amount of fusdc in the predicting pool.

function invested() external view returns (uint256);

timeEnding

function timeEnding() external view returns (uint64);

timeStart

function timeStart() external view returns (uint64);

shareAddr

get a share address using the identifier given instead of an online check.

function shareAddr(bytes8 outcomeId) external view returns (address);

version

function version() external pure returns (string memory);

fees62DAA154

fees currently set in the market. Scaled by FEE_SCALING.

function fees62DAA154() external view returns (Fees memory);

userLiquidityShares

function userLiquidityShares(address spender) external view returns (uint256);

Structs

UserLiqAdded

struct UserLiqAdded {
    bytes8 outcome;
    uint256 sharesReceived;
}

UserLiqRemoved

struct UserLiqRemoved {
    bytes8 outcome;
    uint256 sharesReceived;
}

Fees

struct Fees {
    uint256 feeCreator;
    uint256 feeMinter;
    uint256 feeLp;
    uint256 feeReferrer;
}

ITradingBeacon

Git Source

Functions

mint

function mint() external view returns (address);

quotes

function quotes() external view returns (address);

price

function price() external view returns (address);

extras

function extras() external view returns (address);

IWETH10

Git Source

Functions

deposit

function deposit() external payable;

InfraMarketState

Git Source

enum InfraMarketState {
    Callable,
    Closable,
    Whinging,
    Predicting,
    Revealing,
    Declarable,
    Sweeping,
    Closed
}

LPHelper

Git Source

LPHelper is a simple contract that facilitates LPing multiple trading addresses at once. It can be combined with an off-chain measurement of trading fees and information on popularity to be used.

IERC20

Git Source

Functions

balanceOf

function balanceOf(address) external view returns (uint256);

LensesV1

Git Source

State Variables

LONGTAIL

ILongtail public immutable LONGTAIL;

FACTORY

INineLivesFactory public immutable FACTORY;

Functions

constructor

constructor(ILongtail _longtail, INineLivesFactory _factory);

getLongtailQuote

function getLongtailQuote(address _pool, bool _zeroForOne, int256 _amount, uint256 _priceLimit)
    external
    returns (string memory data);

getShareAddr

function getShareAddr(INineLivesFactory _factory, bytes32 _hash, address _tradingAddr, bytes8 _outcomeId)
    public
    pure
    returns (address shareAddr);

balancesWithFactoryAndHash

function balancesWithFactoryAndHash(
    INineLivesFactory _factory,
    bytes32 _hash,
    address _tradingAddr,
    bytes32[] calldata _words,
    address _spender
) external view returns (uint256[] memory bals);

LockupToken

Git Source

Inherits: Initializable, ERC20Upgradeable, ERC20BurnableUpgradeable, OwnableUpgradeable, ERC20PermitUpgradeable, ERC20VotesUpgradeable

Functions

constructor

Note: oz-upgrades-unsafe-allow: constructor

constructor();

ctor

function ctor(address initialOwner) public initializer;

mint

function mint(address to, uint256 amount) public onlyOwner;

burn

function burn(address to, uint256 amount) public onlyOwner;

clock

function clock() public view override returns (uint48);

CLOCK_MODE

function CLOCK_MODE() public pure override returns (string memory);

_update

function _update(address from, address to, uint256 value) internal override(ERC20Upgradeable, ERC20VotesUpgradeable);

delegate

function delegate(address) public pure override;

delegateBySig

function delegateBySig(address, uint256, uint256, uint8, bytes32, bytes32) public pure override;

nonces

function nonces(address owner) public view override(ERC20PermitUpgradeable, NoncesUpgradeable) returns (uint256);

NinelivesCash

Git Source

Inherits: Initializable, ERC20Upgradeable, OwnableUpgradeable, ERC20PermitUpgradeable

State Variables

debt

mapping(address => uint256) public debt;

Functions

constructor

Note: oz-upgrades-unsafe-allow: constructor

constructor();

initialize

function initialize(address initialOwner) public initializer;

mint

function mint(address to, uint256 amount) public onlyOwner;

NinelivesLockedARB

Git Source

Inherits: Initializable, ERC20Upgradeable, ERC20BurnableUpgradeable, OwnableUpgradeable, ERC20PermitUpgradeable, ERC20VotesUpgradeable

Functions

constructor

Note: oz-upgrades-unsafe-allow: constructor

constructor();

ctor

function ctor(address initialOwner) public initializer;

mint

function mint(address to, uint256 amount) public onlyOwner;

clock

function clock() public view override returns (uint48);

CLOCK_MODE

function CLOCK_MODE() public pure override returns (string memory);

_update

function _update(address from, address to, uint256 value) internal override(ERC20Upgradeable, ERC20VotesUpgradeable);

nonces

function nonces(address owner) public view override(ERC20PermitUpgradeable, NoncesUpgradeable) returns (uint256);

transfer

function transfer(address, uint256) public pure override returns (bool);

transferFrom

function transferFrom(address, address, uint256) public pure override returns (bool);

SARPSignaller

Git Source

Inherits: IEvents

SARPSignaller is a on-chain system with a bond that allows a user to formally request conclusion of a market with SARP. This is done so as an alternative to an off-chain system based on the conclusion of a market.

State Variables

tickets

mapping(uint256 => Ticket) public tickets;

ticketCount

uint256 private ticketCount;

feeCollection

uint256 public feeCollection;

SARP

address immutable SARP;

Functions

constructor

constructor(address _sarp);

request

Request a conclusion to a market using SARP, transferring the bond payment from the user to escrow here for redemption.

function request(address _trading, address _recipient) external;

conclude

Conclude a market if the outcome was not an indeterminate state by refunding the spender. In the calldata, it logs the receipt of the justification for its decision.

function conclude(uint256 _ticket, bytes32 _note) external;

Parameters

NameTypeDescription
_ticketuint256that is relevant to this.
_notebytes32

Structs

Ticket

struct Ticket {
    address addr;
}

Share

Git Source

Inherits: Initializable, ERC20Upgradeable, OwnableUpgradeable, ERC20PermitUpgradeable

State Variables

admin

address public admin;

Functions

constructor

constructor();

ctor

function ctor(string calldata name, address _admin) public initializer;

decimals

function decimals() public pure override returns (uint8);

mint

function mint(address to, uint256 amount) public onlyOwner;

burn

function burn(address owner, uint256 value) public onlyOwner;

TradingBeacon

Git Source

Inherits: ITradingBeacon

State Variables

admin

address public admin;

mint

address public mint;

quotes

address public quotes;

price

address public price;

extras

address public extras;

Functions

constructor

constructor(address _admin, address _mintImpl, address _quotesImpl, address _priceImpl, address _extrasImpl);

shutdown

shutdown the contract by preventing it from servicing any delegatecalls. This is useful in an emergency context.

function shutdown() external;

changeAdmin

function changeAdmin(address _oldAdmin, address _newAdmin) external;

upgradeMint

function upgradeMint(address _oldImpl, address _newImpl) external;

upgradeQuotes

function upgradeQuotes(address _oldImpl, address _newImpl) external;

upgradePrice

function upgradePrice(address _oldImpl, address _newImpl) external;

upgradeExtras

function upgradeExtras(address _oldImpl, address _newImpl) external;

Events

NewAdmin

event NewAdmin(address indexed newAdmin);

UpgradedMint

event UpgradedMint(address indexed impl);

UpgradedQuotes

event UpgradedQuotes(address indexed impl);

UpgradedPrice

event UpgradedPrice(address indexed price);

UpgradedExtras

event UpgradedExtras(address indexed extras);

StorageSlot

Git Source

Functions

getAddressSlot

function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r);

Structs

AddressSlot

struct AddressSlot {
    address value;
}

TradingBeaconProxy

Git Source

This is only useful for a very limited context, which is a limited run "blessed" deployment that's inaccessible using the normal path of addressing trading deployments. This could be useful for experimental releases that need upgradeability. The beacon also has a custom feature to disable the running, useful for an experimental release.

State Variables

BEACON

ITradingBeacon immutable BEACON;

Functions

constructor

constructor(ITradingBeacon _impl);

indicateProxy

indicateProxy is an optional function to indicate the beacon address.

Let's hope we don't have a signature collision here.

function indicateProxy() external;

fallback

fallback() external;

Constants

Git Source

SLOT_BEACON

bytes32 constant SLOT_BEACON = bytes32(uint256(keccak256("eip1967.proxy.beacon")) - 1);

TradingBeaconProxyDeployHelperFactory

Git Source

State Variables

BEACON

ITradingBeacon public immutable BEACON;

IMPL

TradingBeaconProxy immutable IMPL;

Functions

constructor

constructor(address _admin, address _mint, address _quotes, address _price, address _extras);

clone

function clone(address _impl, bytes memory _args) public returns (address instance);

create

function create(CreateArgs calldata _a) external returns (INineLivesTrading);

Events

DeploymentCompleted

event DeploymentCompleted(ITradingBeacon indexed beacon, TradingBeaconProxy indexed impl);

Structs

CreateArgs

struct CreateArgs {
    bytes8[] outcomes;
    address oracle;
    uint64 timeStart;
    uint64 timeEnding;
    address feeRecipient;
    address shareImpl;
    bool shouldBufferTime;
    uint64 feeCreator;
    uint64 feeMinter;
    uint64 feeLp;
    uint64 feeReferrer;
}

IProxy

Git Source

Functions

upgradeAndCall

function upgradeAndCall(address, address, bytes memory) external;

TwoProxyAdmin

Git Source

State Variables

admin

address public admin;

Functions

constructor

constructor(address _admin);

transferOwnership

function transferOwnership(address _newAdmin) external;

upgrade

function upgrade(address _proxy, address _impl1, address _impl2, bytes memory _data) external;

Events

TransferOwnership

event TransferOwnership(address old, address new_);

IBeacon

Git Source

Functions

mintAddr

function mintAddr(bool isDpm) external view returns (address);

quotesAddr

function quotesAddr(bool isDpm) external view returns (address);

priceAddr

function priceAddr(bool isDpm) external view returns (address);

extrasAddr

function extrasAddr(bool isDpm) external view returns (address);

UpgradeableFourBeaconProxy

Git Source

State Variables

BEACON

IBeacon immutable BEACON;

IS_DPM

bool immutable IS_DPM;

Functions

constructor

constructor(IBeacon _b, bool _d);

directDelegate

function directDelegate(address to) internal;

fallback

fallback() external;

StorageSlot

Git Source

Functions

getAddressSlot

function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r);

Structs

AddressSlot

struct AddressSlot {
    address value;
}

UpgradeableTwoProxy

Git Source

UpgradeableTwoProxy is a proxy that does delegation based on the 3rd byte of the signature used in the message received to the contract.

State Variables

admin_

address private immutable admin_;

Functions

constructor

constructor(address _admin, address _impl1, address _impl2, bytes memory _data);

fallback

fallback() external;

Events

Upgraded1

event Upgraded1(address impl);

Upgraded2

event Upgraded2(address impl);

AdminChanged

event AdminChanged(address previousAdmin, address newAdmin);

Constants

Git Source

ADMIN_SLOT

bytes32 constant ADMIN_SLOT = bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1);

IMPL_1_SLOT

bytes32 constant IMPL_1_SLOT = bytes32(uint256(keccak256("eip1967.proxy.implementation.1")) - 1);

IMPL_2_SLOT

bytes32 constant IMPL_2_SLOT = bytes32(uint256(keccak256("eip1967.proxy.implementation.2")) - 1);

WordPackingLib

Git Source

Functions

pack

function pack(bytes8 word1, bytes8 word2, bytes8 word3, bytes8 word4) external pure returns (bytes32 word);

unpack

function unpack(bytes32 word) external pure returns (bytes8, bytes8, bytes8, bytes8);