Numeraire is an ERC20 token used for staking in Numerai's machine learning tournament to solve the stock market. The token mechanics are described in the whitepaper.
Authors: Alex Mingoia, Joey Krug, Xander Dunn, and Philip Monk
Security Audit: Peter Vessenes and Dennis Peterson at New Alchemy. See security_audit.pdf.
- Should require multi-sig for some functions
- Should be able to single-sig pause the contract and multi-sig unpause the contract
- All state-changing functions should be disabled in the paused state unless it requires multi-sig
- Only Numerai can release stakes, destroy stakes, and mint
- Transfers from Numerai's store of NMR require multi-sig
- All NMR initially minted are sent to Numerai's multi-sig
- The contract should be upgradable so that the maps of balances, allowances, and stakes remain unchanged but the functions called for minting, staking, releasing stakes, and destroying stakes are changed.
- It should be possible to disable upgradability forever
- Any address can stake
- Numerai can make a stake on behalf of addresses 0 through 1,000,000
- Stakes are released to the address that made the stake
- In addition to NMR, ETH can be sent to the address that made the released stake
- Clone this repository:
git clone [email protected]:numerai/contract.git && cd contract
- Install dependencies:
npm install
- Install truffle:
sudo npm install -g truffle
- Install testrpc:
sudo npm install -g ethereumjs-testrpc
- Install solc:
- On Ubuntu, this is:
sudo add-apt-repository ppa:ethereum/ethereum sudo apt-get update sudo apt-get install solc
- On Mac:
brew tap ethereum/ethereum brew install solidity
- On Ubuntu, this is:
solc --bin contracts/NumeraireBackend.sol
ortruffle compile
testrpc -p 6545 -u 0x54fd80d6ae7584d8e9a19fe1df43f04e5282cc43 -u 0xa6d135de4acf44f34e2e14a4ee619ce0a99d1e08
to start the test server with the multi-sig keys unlockedtruffle test
to run the tests
General notes:
- All values are specified as
uint256
with 18 decimals. - We throw on error rather than return false.
The following are functions that may be useful for a user to call.
Transfers NMR to another user. This function is part of the ERC20 standard.
_to
is the destination address._value
is the amount to be transferred.
Stakes NMR on a prediction. Users should ensure that their stake is valid according to the rules set forth here.
_value
is the amount to be staked.tag
is used to associate the prediction with a particular submission. Currently, the tag should be the username of the web account that made the submission._tournamentID
is the id of the tournament that the round is in. For now, this is always1
._roundID
is the id of the round._confidence
is the confidence level of the stake with 3 decimals.
Allows another contract to spend on user's behalf. This function is part of the ERC20 standard.
We recommend to use this function with special care since improper use will
result in vulnerability to this attack.
To mitigate this, we require the user set the approval to zero before changing
to another non-zero value. However, in general, changeApproval
is much
safer.
_spender
is the address of the contract._value
is the amount to allow the contract to spend.
Sets the approval to a new value while checking that the previous approval
value is what we expected. This is safer than approve
.
_spender
is the address of the contract._oldValue
is the current amount the contract is allowed to spend._newValue
is the new amount to allow the contract to spend.
Transfers NMR from one address to another. Called by a contract which has been
approved by _from
to spend some of its NMR.
_from
is the source of the NMR. It must have already approved the sender to spend some of its NMR._to
is the destination address._value
is the amount of NMR to transfer.
The following are constant functions (i.e. they don't cause any state change and may be called without submitting a transaction or paying gas costs).
Returns the current supply of NMR. This function is part of the ERC20 standard.
Returns the total NMR ever minted. This will be more than totalSupply
stakes
are destroyed.
Returns the amount of NMR disbursed at deploy time.
Returns 21 million NMR, the total that will ever be minted.
Returns the amount of NMR permitted to be minted every week.
Returns the amount of the NMR that could be minted now.
Returns the timestamp of the block when the contract was deployed.
Returns the balance of the given address. This is part of the ERC20 standard.
Returns the amount that _user
has approved for _contract
to spend.
Returns the token standard, which is "ERC20". This is part of the ERC20 standard.
Returns the human-readable name of the token, which is "Numeraire". This is part of the ERC20 standard.
Returns the human-readable abbreviation of the token, which is "NMR". This is part of the ERC20 standard.
Returns the number of decimals in the canonical representation of NMR amounts, which is 18. This is part of the ERC20 standard.
Returns the address of the delegate contract, which is the upgradeable portion of the contract.
Returns whether the contract is still upgradeable. This can be changed with
disableContractUpgradability
.
Returns the _i
th previous delegate contract.
Returns the creation time and round list for the given tournament.
Returns the creation time, end time, and resolution time for the given round in the given tournament.
getStake(uint256 _tournamentID, uint256 _roundID, address _staker, bytes32 _tag) returns (uint256, uint256, bool, bool)
Returns the stake made by _staker
on user _tag
in round _roundID
of
tournament _tournamentID
. The result includes the confidence level, stake
amount, success, and whether or not the stake has been resolved yet.
Returns the number of contract owner confirmations required for a multi-sig transaction.
Returns the owner at the given index.
Returns true if the address is an owner.
Returns true if the given address is an owner that has confirmed the given operation.
Returns true if the contract is in an emergency stop.
Returns true if the contract can be stopped.
The following events may be emitted by the contract.
Emitted when minting value
NMR.
Emitted when NMR is transferred from one address to another.
Emitted when a user approves a contract to spend an amount of NMR on their behalf.
Staked(address indexed staker, bytes32 tag, uint256 totalAmountStaked, uint256 confidence, uint256 indexed tournamentID, uint256 indexed roundID)
Emitted when a stake is recorded.
Emitted when a tournament is created.
RoundCreated(uint256 indexed tournamentID, uint256 indexed roundID, uint256 endTime, uint256 resolutionTime)
Emitted when a round is created.
StakeReleased(uint256 indexed tournamentID, uint256 indexed roundID, address indexed stakerAddress, bytes32 tag, uint256 etherReward)
Emitted when a stake is released.
StakeDestroyed(uint256 indexed tournamentID, uint256 indexed roundID, address indexed stakerAddress, bytes32 tag)
Emitted when a stake is destroyed.
Emitted when the delegate address has changed.
Emitted when one of the contract owners confirms a multi-sig transaction.
Emitted when one of the contract owners revokes a previous confirmation of a multi-sig transaction.
The following are functions that may only be called by one or more of the contract owners.
Changes the delegate contract.
Permanently disables the changing the delegate contract.
If _token
is 0, then sends all ether in the contract to the sender. If
_token
is the address of an ERC20 token, then this sends all of those tokens
to the sender.
Mints new NMR, depositing it into the balance of the contract.
Transfers NMR from the contract.
stakeOnBehalf(address _staker, uint256 _value, bytes32 _tag, uint256 _tournamentID, uint256 _roundID, uint256 _confidence)
Performs a stake on behalf of a Numerai web user's assigned address. This only
functions when _staker
is no more than 1 million.
releaseStake(address _staker, bytes32 _tag, uint256 _etherValue, uint256 _tournamentID, uint256 _roundID, bool _successful)
Releases a stake after the round has resolved. Sets the stake amount to 0.
Also sends _etherValue
of ether to the address.
Destroys a stake after the round has resolved. Sets the stake amount to 0.
The value of the stake is not returned to the staker, and totalSupply
reduces
by that amount.
Withdraws NMR from a Numerai web account to another address. _from
must be
no more than 1 million.
Creates a tournament with the given ID.
Creates a round in the given tournament with the given end time and resolution time.
Sets a new list of owners and minimum required number of owners for multi-sig transactions.
Revokes a previous confirmation of an operation.
Performs an emergency stop. In an emergency stop, many functions, including staking and transferring, are disabled.
Ends an emergency stop.
Permanently disables the ability to perform an emergency stop.