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.
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.
- Users can choose their favourite achievements to display in a minified form next to their Meow Domain.
- 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.
- A fixed fee is sent to creator of when shares are created.
- Behind the scenes deferring to the AMM model if more than two outcomes.
- Customise the UI of the frontpage for the info
- Stack ranking is done for automated updating of frontpage
- Campaign report functionality. Images are screened automatically for bad content with CSAM
- API to update campaign by the original sender
- 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 name | Deployment address |
---|---|
Proxy admin | 0x6221A9c005F6e47EB398fD867784CacfDcFFF4E7 |
Factory 1 implementation | 0x3302ac14ad6b38baf789571395cc3a54f0f65e52 |
Factory 2 implementation | 0x928b627add9c2a3578b5c178423724f4d20202ed |
Lockup implementation | 0x99596b476d5e16e4a30bd4858dd289a763671294 |
Optimistic infra predict impl | 0xf94aeb587d332d0e7f2f1e2c87ffea1385ff0505 |
Trading DPM mint impl | 0x7b203ff48f76b163bed86b5f2cb66ce6a46d62d4 |
Trading DPM extras impl | 0x81eebeda7eb9f68c9a825c619f5e0d13a117e5f6 |
Trading DPM price impl | 0x8fc31d39edec596e8089b313920c05642e86d549 |
Trading DPM quotes impl | 0x7439ec52bd28c21f59b07a7a12a09c1f7feac7cf |
Trading AMM mint impl | 0x2314c906ebd852a0be249ce49b98ee804078b05e |
Trading AMM extras impl | 0x59c9660f835c1c1c5387a48b9fe8cf7d49020a64 |
Trading AMM price impl | 0x7ff05c8bac0bce55e1519015a4a86fe2b244df88 |
Trading AMM quotes impl | 0x09e99d6c0e57c2cdb715daf1dc66b98e43514fc3 |
Share implementation | 0x3e27e934344bf490457231Cb8F0c0eda7d60C362 |
Lockup token implementation | 0x70143C674A23a43Ad487D33c4035Ba1D012ac598 |
Infrastructure market impl | 0x863642e21a45e824c4f6347a5757e5dcacae11c1 |
Infrastructure market proxy | 0xc4451d8477cd6b92bfa0d3e2662ce0507a8e10b9 |
Lockup proxy | 0x20d2360706086ec9814d15a52ad2d2aec2c43caa |
Lockup token proxy | 0x14c35ba87e8b490761f492382c9249867b82aaf4 |
Factory proxy | 0x7dfe1fa7760131140cfc48b3ea99719203d8f00b |
Helper factory | 0x2965aF7dD96D550d63be1577feC27ae26d2C46F7 |
LensesV1 | 0x051648539bC4a1C247030EABCBC29cfD1887cd83 |
Beauty contest implementation | 0x3421264e413489b1e69ae84ace8c33c6cb7809ff |
Beauty contest proxy | 0x15f4A8a0b8cD0343fAe5a7FC736cD9e0D7bE4d5C |
Sarp AI Resolver | 0x9d73847f1edc930d2a2ee801aeadb4c4567f18e1 |
Helper factory | 0x6e95B1fcca9aBb2D94213AE3ccFCaf5BB8406E6B |
Buy helper2 | 0xEBBfeAcbbD331466512A362BEa782e1f7CB45b57 |
SARP Signaller | 0xD608CeF1D7C84feaA0E1520C7a6BC4798cFC1455 |
Extras beacon proxy factory | 0x6c1cf52961C567965AFCf495B7af7eCC81411598 |
Superposition testnet
Deployment name | Deployment address |
---|---|
Proxy admin | 0xfeb6034fc7df27df18a3a6bad5fb94c0d3dcb6d5 |
Factory 1 implementation | 0x9e16b693e71d0be52da2158ac6dd2c3b75fbadf0 |
Factory 2 implementation | 0xaca4f34b884969605e7922f44748b5c5a7fb2246 |
Lockup implementation | 0x9733dd5d7e1b42f39b4227e4b0b0e17ff440b3c2 |
Optimistic infra predict impl | 0xe2175ab2ef7aa29ec61657e505e641a5ff509b72 |
Trading DPM mint impl | 0x11a4b84a7d0979e906c8eaba7c16579a3bf48bf5 |
Trading DPM extras impl | 0xbd03aff1a558d0806eed2e6e6af48453daf4de40 |
Trading DPM quotes impl | 0xccf0aed8c4157cfbc41ad0cd78b23c6fd637271e |
Trading DPM price impl | 0x3c3363a60cf654c84915495f2efdd8dd4c3439af |
Trading AMM mint impl | 0x76c1127f1aa1b4f8b33e6137051df91c50d6eee6 |
Trading AMM extras impl | 0xbf5776e6231d511af57a87141adc1217a695f58b |
Trading AMM quotes impl | 0x70a9500293622ff935aa9f65818b80fdbfd9157e |
Trading AMM price impl | 0x4b78c4f0ebeaa1ba42e0d48e7f0cd3c53e1796b9 |
Share implementation | 0xC876Fc7ddd41ae072a8898445f83bBfcC903c195 |
Lockup token implementation | 0xD813030d171026B42bd9D29aE44b3a5a600cFFf7 |
Infrastructure market proxy | 0x1b508fb73912eb306f4ca29cab096c75074ceee4 |
Lockup proxy | 0x397420c66164632937a19768174ee7e21c0df3a2 |
Lockup token proxy | 0xc9ca48f56454be7ce44b929506b32b61c0c8f6d9 |
Factory proxy | 0x48b9cf07bb9dedc7eb33868693b63b28b253f282 |
Helper factory | 0x6E0fc15eFc574e17DC181753fdD5852A1c963D97 |
LensesV1 | 0x61F92c803177c1060Ef7B360bD631d857B1545B9 |
Beauty contest implementation | 0x40e652ce259d6de7dd4058ce5c255a44785fc4e7 |
Beauty contest proxy | 0xc3d76a0b0ca758648b56e2535712f4a9316cb709 |
Sarp AI Resolver | 0x0000000000000000000000000000000000000000 |
Buy helper2 | 0x491286b009F19300ac45ed5571e012F125AB9B9d |
SARP Signaller | 0x2137B4C506f0d7eF2A562B02Be9110a4a3A93bC9 |
IERC20
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
Functions
mintPermitE90275AB
function mintPermitE90275AB(bytes8, uint256, address, uint256, uint8, bytes32, bytes32) external returns (uint256);
BuyHelper2
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
Functions
ctor
function ctor(address admin, address emergency, ILockup lockup, address lockedArbToken, INineLivesFactory factoryAddr)
external;
Lockup
Functions
ctor
function ctor(address tokenImpl, address infraMarket, address operator) external;
Factory
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
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
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
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
Functions
deploy
function deploy(address _owner, address _default) external returns (address beacon, address proxy);
ExtrasBeaconProxy
State Variables
BEACON
ExtrasBeacon immutable BEACON;
Functions
constructor
constructor(ExtrasBeacon _b);
fallback
fallback() external;
IERC20Permit
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
struct CreateArgs {
address oracle;
FactoryOutcome[] outcomes;
uint64 timeEnding;
bytes32 documentation;
address feeRecipient;
uint64 feeCreator;
uint64 feeLp;
uint64 feeMinter;
uint64 feeReferrer;
uint256 seedLiquidity;
}
HelperFactory
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
INCENTIVE_AMT_MODERATION
uint256 constant INCENTIVE_AMT_MODERATION = 1e6;
INCENTIVE_INFRA_MARKET
uint256 constant INCENTIVE_INFRA_MARKET = 2200000;
IDecidable
Functions
decide
Decide an outcome. Only callable by the oracle!
function decide(bytes8 outcome) external;
Parameters
Name | Type | Description |
---|---|---|
outcome | bytes8 | to set as the winner. |
escape
Escape an indeterminate/inconclusive campaign, where an associated contract needs to do something.
function escape() external;
IEvents
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
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
Name | Type | Description |
---|---|---|
trading | address | address to configure this |
desc | bytes32 | of the contract to commit as info for users. Should be info for a oracle. |
launchTs | uint64 | to use as the timestamp to begin this infra market. Could be the conclusion date. |
callDeadlineTs | uint64 |
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
Name | Type | Description |
---|---|---|
tradingAddr | address | to call for. |
winner | bytes8 | to indicate is the preferred outcome by this user. |
incentiveRecipient | address | to 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
Name | Type | Description |
---|---|---|
tradingAddr | address | to use for the disagreement that's taking place. |
preferredOutcome | bytes8 | to use as the outcome that the whinger disagrees is the best. |
bondRecipient | address | to 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
Name | Type | Description |
---|---|---|
tradingAddr | address | to use as the trading address to make commitments for. |
commit | bytes32 | to 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
Name | Type | Description |
---|---|---|
trading | address | contract this is for. |
outcome | bytes8 | that 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
Name | Type | Description |
---|---|---|
trading | address | to check. |
whingerPreferredWinner
Get the preferred whinger of the infra market given.
function whingerPreferredWinner(address trading) external view returns (bytes8);
Parameters
Name | Type | Description |
---|---|---|
trading | address | contract 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
Name | Type | Description |
---|---|---|
trading | address | contract 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
Name | Type | Description |
---|---|---|
tradingAddr | address | to use as the place for the commitments to be tracked. |
committerAddr | address | to use as the address of the user making commitments. |
outcome | bytes8 | to state the previously made commitment was for. |
seed | uint256 | to 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
Name | Type | Description |
---|---|---|
tradingAddr | address | to use as the trading address for the campaign. |
epochNo | uint256 | to use as the epoch number to take funds from. |
victim | address | to claim funds from. |
feeRecipientAddr | address | to 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
Name | Type | Description |
---|---|---|
tradingAddr | address | to capture amounts from. |
epochNo | uint256 | to collect amounts from the pot from. |
feeRecipient | address | to 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
Name | Type | Description |
---|---|---|
tradingAddr | address | this market is for. |
feeRecipient | address | to 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
Name | Type | Description |
---|---|---|
tradingAddr | address | to 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
Name | Type | Description |
---|---|---|
tradingAddr | address | to use as the trading address for the campaign. |
outcomes | bytes8[] | to use as the outcomes that were in use. |
feeRecipient | address | to send the incentive for declaring to. |
enableContract
Enable or disable the contract.
function enableContract(bool status) external returns (bool);
Parameters
Name | Type | Description |
---|---|---|
status | bool | to set the contract to. |
ILockup
Functions
lockup
Lockup ARB to receive LARB.
function lockup(uint256 amount, address recipient) external returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
amount | uint256 | to lock up. |
recipient | address | to send the Locked ARB to. |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | the 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
Name | Type | Description |
---|---|---|
spender | address | to get the locked until for. |
withdraw
Withdraw some LARB to ARB.
function withdraw(uint256 amount, address recipient) external returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
amount | uint256 | to withdraw. |
recipient | address | to send the returned amounts to. |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | the 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
Name | Type | Description |
---|---|---|
victim | address | to take money from. |
amount | uint256 | to take from the victim. |
recipient | address | to send the slashed amounts to. |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | amount 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
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
struct FactoryOutcome {
bytes8 identifier;
uint256 sqrtPrice;
string name;
}
INineLivesFactory
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
Name | Type | Description |
---|---|---|
outcomes | FactoryOutcome[] | to set up as the default |
oracle | address | to 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. |
timeStart | uint64 | to begin this contract at. This should be in the future. |
timeEnding | uint64 | to end this contract at. This should be in the future. |
documentation | bytes32 | keccak'd hash of the information that makes up the description for infrastructure markets. This is sent out there. |
feeRecipient | address | to send fees earned from the creator commission to. |
feeCreator | uint64 | pct to take as fees for the creator given. |
feeLp | uint64 | pct to take as fees for LPs who use the add/remove liquidity features. |
feeMinter | uint64 | pct to take as fees for users using the mint function. |
feeReferrer | uint64 |
Returns
Name | Type | Description |
---|---|---|
tradingAddr | address | address 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
Name | Type | Description |
---|---|---|
addr | address | is 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
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
Name | Type | Description |
---|---|---|
outcomes | bytes8[] | to use to use as betting outcomes in this contract. |
oracle | address | to use as the resolver for this contract. |
timeStart | uint64 | to begin this contract by. |
timeEnding | uint64 | to end this contract by. |
feeRecipient | address | to send fees earned from trading. |
shareImpl | address | |
shouldBufferTime | bool | to 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. |
feeCreator | uint64 | to take as the default fee from every mint for the creator of this contract. |
feeMinter | uint64 | to take as the fee that we give to minters. |
feeLp | uint64 | to take as a fee for the market makers who used the add/remove features. |
feeReferrer | uint64 | to take and distribute to a referrer for a allocation. |
INineLivesTrading
Functions
ctor
ctor to set the values for this contract.
function ctor(CtorArgs calldata ctorArgs) external;
Parameters
Name | Type | Description |
---|---|---|
ctorArgs | CtorArgs | to 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
Name | Type | Description |
---|---|---|
outcome | bytes8 | to test for |
fusdcValue | uint256 | to 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
Name | Type | Description |
---|---|---|
recipient | address | to send the rewards to. |
priceA827ED27
Get the price of an outcome in fUSDC.
function priceA827ED27(bytes8 outcome) external returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
outcome | bytes8 | to 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
Name | Type | Description |
---|---|---|
outcome | bytes8 | to set as the winner. |
payoffCB6F2565
Collect the payoff if holding winning shares!
function payoffCB6F2565(bytes8 outcomeId, uint256 amount, address recipient) external returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
outcomeId | bytes8 | to collect the payoff for. |
amount | uint256 | of share to use for receiving the payoff. |
recipient | address | to 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
Name | Type | Description |
---|---|---|
outcomeId | bytes8 | to 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
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
Functions
deposit
function deposit() external payable;
InfraMarketState
enum InfraMarketState {
Callable,
Closable,
Whinging,
Predicting,
Revealing,
Declarable,
Sweeping,
Closed
}
LPHelper
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
Functions
balanceOf
function balanceOf(address) external view returns (uint256);
LensesV1
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
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
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
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
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
Name | Type | Description |
---|---|---|
_ticket | uint256 | that is relevant to this. |
_note | bytes32 |
Structs
Ticket
struct Ticket {
address addr;
}
Share
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
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
Functions
getAddressSlot
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r);
Structs
AddressSlot
struct AddressSlot {
address value;
}
TradingBeaconProxy
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
SLOT_BEACON
bytes32 constant SLOT_BEACON = bytes32(uint256(keccak256("eip1967.proxy.beacon")) - 1);
TradingBeaconProxyDeployHelperFactory
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
Functions
upgradeAndCall
function upgradeAndCall(address, address, bytes memory) external;
TwoProxyAdmin
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
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
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
Functions
getAddressSlot
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r);
Structs
AddressSlot
struct AddressSlot {
address value;
}
UpgradeableTwoProxy
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
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
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);