Transaction Hash:
Block:
11973034 at Mar-04-2021 05:02:15 PM +UTC
Transaction Fee:
0.006446464 ETH
$16.65
Gas Used:
50,363 Gas / 128 Gwei
Emitted Events:
387 |
NumeraireBackend.Transfer( from=0x0000000000000000000000000000000000004bd0, to=0x0000000000000000000000000000000000021bb8, value=1000000000000000000000 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x1248C66B...FE421e210 |
7.512220894361849217 Eth
Nonce: 3943
|
7.505774430361849217 Eth
Nonce: 3944
| 0.006446464 | ||
0x1776e1F2...d3Cb46671 | |||||
0xee2FE52A...d2076B93d
Miner
| 6,762.367921907019961823 Eth | 6,762.374368371019961823 Eth | 0.006446464 |
Execution Trace
AdminUpgradeabilityProxy.d9caed12( )
NumeraiErasureV1.withdraw( from=0x0000000000000000000000000000000000004bd0, to=0x0000000000000000000000000000000000021bb8, value=1000000000000000000000 )
Relay.withdraw( _from=0x0000000000000000000000000000000000004bd0, _to=0x0000000000000000000000000000000000021bb8, _value=1000000000000000000000 ) => ( ok=True )
NumeraireBackend.withdraw( _from=0x0000000000000000000000000000000000004bd0, _to=0x0000000000000000000000000000000000021bb8, _value=1000000000000000000000 ) => ( ok=True )
-
NumeraireDelegateV3.withdraw( _from=0x0000000000000000000000000000000000004bd0, _to=0x0000000000000000000000000000000000021bb8, _value=1000000000000000000000 ) => ( ok=True )
-
withdraw[NumeraiErasureV1 (ln:566)]
withdraw[NumeraiErasureV1 (ln:571)]
File 1 of 5: AdminUpgradeabilityProxy
File 2 of 5: NumeraireBackend
File 3 of 5: NumeraiErasureV1
File 4 of 5: Relay
File 5 of 5: NumeraireDelegateV3
pragma solidity >=0.4.24 <0.6.0; /** * @title Proxy * @dev Implements delegation of calls to other contracts, with proper * forwarding of return values and bubbling of failures. * It defines a fallback function that delegates all calls to the address * returned by the abstract _implementation() internal function. */ contract Proxy { /** * @dev Fallback function. * Implemented entirely in `_fallback`. */ function () payable external { _fallback(); } /** * @return The Address of the implementation. */ function _implementation() internal view returns (address); /** * @dev Delegates execution to an implementation contract. * This is a low level function that doesn't return to its internal call site. * It will return to the external caller whatever the implementation returns. * @param implementation Address to delegate. */ function _delegate(address implementation) internal { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize) } default { return(0, returndatasize) } } } /** * @dev Function that is run as the first thing in the fallback function. * Can be redefined in derived contracts to add functionality. * Redefinitions must call super._willFallback(). */ function _willFallback() internal { } /** * @dev fallback implementation. * Extracted to enable manual triggering. */ function _fallback() internal { _willFallback(); _delegate(_implementation()); } } /** * Utility library of inline functions on addresses * * Source https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-solidity/v2.0.0/contracts/utils/Address.sol * This contract is copied here and renamed from the original to avoid clashes in the compiled artifacts * when the user imports a zos-lib contract (that transitively causes this contract to be compiled and added to the * build/artifacts folder) as well as the vanilla Address implementation from an openzeppelin version. */ library ZOSLibAddress { /** * Returns whether the target address is a contract * @dev This function will return false if invoked during the constructor of a contract, * as the code is not actually created until after the constructor finishes. * @param account address of the account to check * @return whether the target address is a contract */ function isContract(address account) internal view returns (bool) { uint256 size; // XXX Currently there is no better way to check if there is a contract in an address // than to check the size of the code at that address. // See https://ethereum.stackexchange.com/a/14016/36603 // for more details about how this works. // TODO Check this again before the Serenity release, because all addresses will be // contracts then. // solium-disable-next-line security/no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } } /** * @title UpgradeabilityProxy * @dev This contract implements a proxy that allows to change the * implementation address to which it will delegate. * Such a change is called an implementation upgrade. */ contract UpgradeabilityProxy is Proxy { /** * @dev Emitted when the implementation is upgraded. * @param implementation Address of the new implementation. */ event Upgraded(address indexed implementation); /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "org.zeppelinos.proxy.implementation", and is * validated in the constructor. */ bytes32 private constant IMPLEMENTATION_SLOT = 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3; /** * @dev Contract constructor. * @param _implementation Address of the initial implementation. * @param _data Data to send as msg.data to the implementation to initialize the proxied contract. * It should include the signature and the parameters of the function to be called, as described in * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. */ constructor(address _implementation, bytes memory _data) public payable { assert(IMPLEMENTATION_SLOT == keccak256("org.zeppelinos.proxy.implementation")); _setImplementation(_implementation); if(_data.length > 0) { (bool ok,) = _implementation.delegatecall(_data); require(ok); } } /** * @dev Returns the current implementation. * @return Address of the current implementation */ function _implementation() internal view returns (address impl) { bytes32 slot = IMPLEMENTATION_SLOT; assembly { impl := sload(slot) } } /** * @dev Upgrades the proxy to a new implementation. * @param newImplementation Address of the new implementation. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Sets the implementation address of the proxy. * @param newImplementation Address of the new implementation. */ function _setImplementation(address newImplementation) private { require(ZOSLibAddress.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address"); bytes32 slot = IMPLEMENTATION_SLOT; assembly { sstore(slot, newImplementation) } } } /** * @title AdminUpgradeabilityProxy * @dev This contract combines an upgradeability proxy with an authorization * mechanism for administrative tasks. * All external functions in this contract must be guarded by the * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity * feature proposal that would enable this to be done automatically. */ contract AdminUpgradeabilityProxy is UpgradeabilityProxy { /** * @dev Emitted when the administration has been transferred. * @param previousAdmin Address of the previous admin. * @param newAdmin Address of the new admin. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "org.zeppelinos.proxy.admin", and is * validated in the constructor. */ bytes32 private constant ADMIN_SLOT = 0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b; /** * @dev Modifier to check whether the `msg.sender` is the admin. * If it is, it will run the function. Otherwise, it will delegate the call * to the implementation. */ modifier ifAdmin() { if (msg.sender == _admin()) { _; } else { _fallback(); } } /** * Contract constructor. * @param _implementation address of the initial implementation. * @param _admin Address of the proxy administrator. * @param _data Data to send as msg.data to the implementation to initialize the proxied contract. * It should include the signature and the parameters of the function to be called, as described in * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. */ constructor(address _implementation, address _admin, bytes memory _data) UpgradeabilityProxy(_implementation, _data) public payable { assert(ADMIN_SLOT == keccak256("org.zeppelinos.proxy.admin")); _setAdmin(_admin); } /** * @return The address of the proxy admin. */ function admin() external ifAdmin returns (address) { return _admin(); } /** * @return The address of the implementation. */ function implementation() external ifAdmin returns (address) { return _implementation(); } /** * @dev Changes the admin of the proxy. * Only the current admin can call this function. * @param newAdmin Address to transfer proxy administration to. */ function changeAdmin(address newAdmin) external ifAdmin { require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address"); emit AdminChanged(_admin(), newAdmin); _setAdmin(newAdmin); } /** * @dev Upgrade the backing implementation of the proxy. * Only the admin can call this function. * @param newImplementation Address of the new implementation. */ function upgradeTo(address newImplementation) external ifAdmin { _upgradeTo(newImplementation); } /** * @dev Upgrade the backing implementation of the proxy and call a function * on the new implementation. * This is useful to initialize the proxied contract. * @param newImplementation Address of the new implementation. * @param data Data to send as msg.data in the low level call. * It should include the signature and the parameters of the function to be called, as described in * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. */ function upgradeToAndCall(address newImplementation, bytes calldata data) payable external ifAdmin { _upgradeTo(newImplementation); (bool ok,) = newImplementation.delegatecall(data); require(ok); } /** * @return The admin slot. */ function _admin() internal view returns (address adm) { bytes32 slot = ADMIN_SLOT; assembly { adm := sload(slot) } } /** * @dev Sets the address of the proxy admin. * @param newAdmin Address of the new proxy admin. */ function _setAdmin(address newAdmin) internal { bytes32 slot = ADMIN_SLOT; assembly { sstore(slot, newAdmin) } } /** * @dev Only fall back when the sender is not the admin. */ function _willFallback() internal { require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin"); super._willFallback(); } }
File 2 of 5: NumeraireBackend
pragma solidity ^0.4.11; contract Safe { // Check if it is safe to add two numbers function safeAdd(uint a, uint b) internal returns (uint) { uint c = a + b; assert(c >= a && c >= b); return c; } // Check if it is safe to subtract two numbers function safeSubtract(uint a, uint b) internal returns (uint) { uint c = a - b; assert(b <= a && c <= a); return c; } function safeMultiply(uint a, uint b) internal returns (uint) { uint c = a * b; assert(a == 0 || (c / a) == b); return c; } function shrink128(uint a) internal returns (uint128) { assert(a < 0x100000000000000000000000000000000); return uint128(a); } // mitigate short address attack modifier onlyPayloadSize(uint numWords) { assert(msg.data.length == numWords * 32 + 4); _; } // allow ether to be received function () payable { } } // Class variables used both in NumeraireBackend and NumeraireDelegate contract NumeraireShared is Safe { address public numerai = this; // Cap the total supply and the weekly supply uint256 public supply_cap = 21000000e18; // 21 million uint256 public weekly_disbursement = 96153846153846153846153; uint256 public initial_disbursement; uint256 public deploy_time; uint256 public total_minted; // ERC20 requires totalSupply, balanceOf, and allowance uint256 public totalSupply; mapping (address => uint256) public balanceOf; mapping (address => mapping (address => uint256)) public allowance; mapping (uint => Tournament) public tournaments; // tournamentID struct Tournament { uint256 creationTime; uint256[] roundIDs; mapping (uint256 => Round) rounds; // roundID } struct Round { uint256 creationTime; uint256 endTime; uint256 resolutionTime; mapping (address => mapping (bytes32 => Stake)) stakes; // address of staker } // The order is important here because of its packing characteristics. // Particularly, `amount` and `confidence` are in the *same* word, so // Solidity can update both at the same time (if the optimizer can figure // out that you're updating both). This makes `stake()` cheap. struct Stake { uint128 amount; // Once the stake is resolved, this becomes 0 uint128 confidence; bool successful; bool resolved; } // Generates a public event on the blockchain to notify clients event Mint(uint256 value); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); event Staked(address indexed staker, bytes32 tag, uint256 totalAmountStaked, uint256 confidence, uint256 indexed tournamentID, uint256 indexed roundID); event RoundCreated(uint256 indexed tournamentID, uint256 indexed roundID, uint256 endTime, uint256 resolutionTime); event TournamentCreated(uint256 indexed tournamentID); event StakeDestroyed(uint256 indexed tournamentID, uint256 indexed roundID, address indexed stakerAddress, bytes32 tag); event StakeReleased(uint256 indexed tournamentID, uint256 indexed roundID, address indexed stakerAddress, bytes32 tag, uint256 etherReward); // Calculate allowable disbursement function getMintable() constant returns (uint256) { return safeSubtract( safeAdd(initial_disbursement, safeMultiply(weekly_disbursement, safeSubtract(block.timestamp, deploy_time)) / 1 weeks), total_minted); } } // From OpenZepplin: https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/ownership/Shareable.sol /* * Shareable * * Effectively our multisig contract * * Based on https://github.com/ethereum/dapp-bin/blob/master/wallet/wallet.sol * * inheritable "property" contract that enables methods to be protected by requiring the acquiescence of either a single, or, crucially, each of a number of, designated owners. * * usage: * use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by some number (specified in constructor) of the set of owners (specified in the constructor) before the interior is executed. */ contract Shareable { // TYPES // struct for the status of a pending operation. struct PendingState { uint yetNeeded; uint ownersDone; uint index; } // FIELDS // the number of owners that must confirm the same operation before it is run. uint public required; // list of owners address[256] owners; uint constant c_maxOwners = 250; // index on the list of owners to allow reverse lookup mapping(address => uint) ownerIndex; // the ongoing operations. mapping(bytes32 => PendingState) pendings; bytes32[] pendingsIndex; // EVENTS // this contract only has six types of events: it can accept a confirmation, in which case // we record owner and operation (hash) alongside it. event Confirmation(address owner, bytes32 operation); event Revoke(address owner, bytes32 operation); // MODIFIERS address thisContract = this; // simple single-sig function modifier. modifier onlyOwner { if (isOwner(msg.sender)) _; } // multi-sig function modifier: the operation must have an intrinsic hash in order // that later attempts can be realised as the same underlying operation and // thus count as confirmations. modifier onlyManyOwners(bytes32 _operation) { if (confirmAndCheck(_operation)) _; } // CONSTRUCTOR // constructor is given number of sigs required to do protected "onlymanyowners" transactions // as well as the selection of addresses capable of confirming them. function Shareable(address[] _owners, uint _required) { owners[1] = msg.sender; ownerIndex[msg.sender] = 1; for (uint i = 0; i < _owners.length; ++i) { owners[2 + i] = _owners[i]; ownerIndex[_owners[i]] = 2 + i; } if (required > owners.length) throw; required = _required; } // new multisig is given number of sigs required to do protected "onlymanyowners" transactions // as well as the selection of addresses capable of confirming them. // take all new owners as an array function changeShareable(address[] _owners, uint _required) onlyManyOwners(sha3(msg.data)) { for (uint i = 0; i < _owners.length; ++i) { owners[1 + i] = _owners[i]; ownerIndex[_owners[i]] = 1 + i; } if (required > owners.length) throw; required = _required; } // METHODS // Revokes a prior confirmation of the given operation function revoke(bytes32 _operation) external { uint index = ownerIndex[msg.sender]; // make sure they're an owner if (index == 0) return; uint ownerIndexBit = 2**index; var pending = pendings[_operation]; if (pending.ownersDone & ownerIndexBit > 0) { pending.yetNeeded++; pending.ownersDone -= ownerIndexBit; Revoke(msg.sender, _operation); } } // Gets an owner by 0-indexed position (using numOwners as the count) function getOwner(uint ownerIndex) external constant returns (address) { return address(owners[ownerIndex + 1]); } function isOwner(address _addr) constant returns (bool) { return ownerIndex[_addr] > 0; } function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool) { var pending = pendings[_operation]; uint index = ownerIndex[_owner]; // make sure they're an owner if (index == 0) return false; // determine the bit to set for this owner. uint ownerIndexBit = 2**index; return !(pending.ownersDone & ownerIndexBit == 0); } // INTERNAL METHODS function confirmAndCheck(bytes32 _operation) internal returns (bool) { // determine what index the present sender is: uint index = ownerIndex[msg.sender]; // make sure they're an owner if (index == 0) return; var pending = pendings[_operation]; // if we're not yet working on this operation, switch over and reset the confirmation status. if (pending.yetNeeded == 0) { // reset count of confirmations needed. pending.yetNeeded = required; // reset which owners have confirmed (none) - set our bitmap to 0. pending.ownersDone = 0; pending.index = pendingsIndex.length++; pendingsIndex[pending.index] = _operation; } // determine the bit to set for this owner. uint ownerIndexBit = 2**index; // make sure we (the message sender) haven't confirmed this operation previously. if (pending.ownersDone & ownerIndexBit == 0) { Confirmation(msg.sender, _operation); // ok - check if count is enough to go ahead. if (pending.yetNeeded <= 1) { // enough confirmations: reset and run interior. delete pendingsIndex[pendings[_operation].index]; delete pendings[_operation]; return true; } else { // not enough: record that this owner in particular confirmed. pending.yetNeeded--; pending.ownersDone |= ownerIndexBit; } } } function clearPending() internal { uint length = pendingsIndex.length; for (uint i = 0; i < length; ++i) if (pendingsIndex[i] != 0) delete pendings[pendingsIndex[i]]; delete pendingsIndex; } } // From OpenZepplin: https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/lifecycle/Pausable.sol /* * Stoppable * Abstract contract that allows children to implement an * emergency stop mechanism. */ contract StoppableShareable is Shareable { bool public stopped; bool public stoppable = true; modifier stopInEmergency { if (!stopped) _; } modifier onlyInEmergency { if (stopped) _; } function StoppableShareable(address[] _owners, uint _required) Shareable(_owners, _required) { } // called by the owner on emergency, triggers stopped state function emergencyStop() external onlyOwner { assert(stoppable); stopped = true; } // called by the owners on end of emergency, returns to normal state function release() external onlyManyOwners(sha3(msg.data)) { assert(stoppable); stopped = false; } // called by the owners to disable ability to begin or end an emergency stop function disableStopping() external onlyManyOwners(sha3(msg.data)) { stoppable = false; } } // This is the contract that will be unchangeable once deployed. It will call delegate functions in another contract to change state. The delegate contract is upgradable. contract NumeraireBackend is StoppableShareable, NumeraireShared { address public delegateContract; bool public contractUpgradable = true; address[] public previousDelegates; string public standard = "ERC20"; // ERC20 requires name, symbol, and decimals string public name = "Numeraire"; string public symbol = "NMR"; uint256 public decimals = 18; event DelegateChanged(address oldAddress, address newAddress); function NumeraireBackend(address[] _owners, uint256 _num_required, uint256 _initial_disbursement) StoppableShareable(_owners, _num_required) { totalSupply = 0; total_minted = 0; initial_disbursement = _initial_disbursement; deploy_time = block.timestamp; } function disableContractUpgradability() onlyManyOwners(sha3(msg.data)) returns (bool) { assert(contractUpgradable); contractUpgradable = false; } function changeDelegate(address _newDelegate) onlyManyOwners(sha3(msg.data)) returns (bool) { assert(contractUpgradable); if (_newDelegate != delegateContract) { previousDelegates.push(delegateContract); var oldDelegate = delegateContract; delegateContract = _newDelegate; DelegateChanged(oldDelegate, _newDelegate); return true; } return false; } function claimTokens(address _token) onlyOwner { assert(_token != numerai); if (_token == 0x0) { msg.sender.transfer(this.balance); return; } NumeraireBackend token = NumeraireBackend(_token); uint256 balance = token.balanceOf(this); token.transfer(msg.sender, balance); } function mint(uint256 _value) stopInEmergency returns (bool ok) { return delegateContract.delegatecall(bytes4(sha3("mint(uint256)")), _value); } function stake(uint256 _value, bytes32 _tag, uint256 _tournamentID, uint256 _roundID, uint256 _confidence) stopInEmergency returns (bool ok) { return delegateContract.delegatecall(bytes4(sha3("stake(uint256,bytes32,uint256,uint256,uint256)")), _value, _tag, _tournamentID, _roundID, _confidence); } function stakeOnBehalf(address _staker, uint256 _value, bytes32 _tag, uint256 _tournamentID, uint256 _roundID, uint256 _confidence) stopInEmergency onlyPayloadSize(6) returns (bool ok) { return delegateContract.delegatecall(bytes4(sha3("stakeOnBehalf(address,uint256,bytes32,uint256,uint256,uint256)")), _staker, _value, _tag, _tournamentID, _roundID, _confidence); } function releaseStake(address _staker, bytes32 _tag, uint256 _etherValue, uint256 _tournamentID, uint256 _roundID, bool _successful) stopInEmergency onlyPayloadSize(6) returns (bool ok) { return delegateContract.delegatecall(bytes4(sha3("releaseStake(address,bytes32,uint256,uint256,uint256,bool)")), _staker, _tag, _etherValue, _tournamentID, _roundID, _successful); } function destroyStake(address _staker, bytes32 _tag, uint256 _tournamentID, uint256 _roundID) stopInEmergency onlyPayloadSize(4) returns (bool ok) { return delegateContract.delegatecall(bytes4(sha3("destroyStake(address,bytes32,uint256,uint256)")), _staker, _tag, _tournamentID, _roundID); } function numeraiTransfer(address _to, uint256 _value) onlyPayloadSize(2) returns(bool ok) { return delegateContract.delegatecall(bytes4(sha3("numeraiTransfer(address,uint256)")), _to, _value); } function withdraw(address _from, address _to, uint256 _value) onlyPayloadSize(3) returns(bool ok) { return delegateContract.delegatecall(bytes4(sha3("withdraw(address,address,uint256)")), _from, _to, _value); } function createTournament(uint256 _tournamentID) returns (bool ok) { return delegateContract.delegatecall(bytes4(sha3("createTournament(uint256)")), _tournamentID); } function createRound(uint256 _tournamentID, uint256 _roundID, uint256 _endTime, uint256 _resolutionTime) returns (bool ok) { return delegateContract.delegatecall(bytes4(sha3("createRound(uint256,uint256,uint256,uint256)")), _tournamentID, _roundID, _endTime, _resolutionTime); } function getTournament(uint256 _tournamentID) constant returns (uint256, uint256[]) { var tournament = tournaments[_tournamentID]; return (tournament.creationTime, tournament.roundIDs); } function getRound(uint256 _tournamentID, uint256 _roundID) constant returns (uint256, uint256, uint256) { var round = tournaments[_tournamentID].rounds[_roundID]; return (round.creationTime, round.endTime, round.resolutionTime); } function getStake(uint256 _tournamentID, uint256 _roundID, address _staker, bytes32 _tag) constant returns (uint256, uint256, bool, bool) { var stake = tournaments[_tournamentID].rounds[_roundID].stakes[_staker][_tag]; return (stake.confidence, stake.amount, stake.successful, stake.resolved); } // ERC20: Send from a contract function transferFrom(address _from, address _to, uint256 _value) stopInEmergency onlyPayloadSize(3) returns (bool ok) { require(!isOwner(_from) && _from != numerai); // Transfering from Numerai can only be done with the numeraiTransfer function // Check for sufficient funds. require(balanceOf[_from] >= _value); // Check for authorization to spend. require(allowance[_from][msg.sender] >= _value); balanceOf[_from] = safeSubtract(balanceOf[_from], _value); allowance[_from][msg.sender] = safeSubtract(allowance[_from][msg.sender], _value); balanceOf[_to] = safeAdd(balanceOf[_to], _value); // Notify anyone listening. Transfer(_from, _to, _value); return true; } // ERC20: Anyone with NMR can transfer NMR function transfer(address _to, uint256 _value) stopInEmergency onlyPayloadSize(2) returns (bool ok) { // Check for sufficient funds. require(balanceOf[msg.sender] >= _value); balanceOf[msg.sender] = safeSubtract(balanceOf[msg.sender], _value); balanceOf[_to] = safeAdd(balanceOf[_to], _value); // Notify anyone listening. Transfer(msg.sender, _to, _value); return true; } // ERC20: Allow other contracts to spend on sender's behalf function approve(address _spender, uint256 _value) stopInEmergency onlyPayloadSize(2) returns (bool ok) { require((_value == 0) || (allowance[msg.sender][_spender] == 0)); allowance[msg.sender][_spender] = _value; Approval(msg.sender, _spender, _value); return true; } function changeApproval(address _spender, uint256 _oldValue, uint256 _newValue) stopInEmergency onlyPayloadSize(3) returns (bool ok) { require(allowance[msg.sender][_spender] == _oldValue); allowance[msg.sender][_spender] = _newValue; Approval(msg.sender, _spender, _newValue); return true; } }
File 3 of 5: NumeraiErasureV1
pragma solidity >=0.5.0 <0.6.0; interface IRelay { /// @notice Transfer NMR on behalf of a Numerai user /// Can only be called by Manager or Owner /// @dev Can only be used on the first 1 million ethereum addresses /// @param _from The user address /// @param _to The recipient address /// @param _value The amount of NMR in wei function withdraw(address _from, address _to, uint256 _value) external returns (bool ok); /// @notice Burn the NMR sent to address 0 and burn address function burnZeroAddress() external; /// @notice Permanantly disable the relay contract /// Can only be called by Owner function disable() external; /// @notice Permanantly disable token upgradability /// Can only be called by Owner function disableTokenUpgradability() external; /// @notice Upgrade the token delegate logic. /// Can only be called by Owner /// @param _newDelegate Address of the new delegate contract function changeTokenDelegate(address _newDelegate) external; /// @notice Upgrade the token delegate logic using the UpgradeDelegate /// Can only be called by Owner /// @dev must be called after UpgradeDelegate is set as the token delegate /// @param _multisig Address of the multisig wallet address to receive NMR and ETH /// @param _delegateV3 Address of NumeraireDelegateV3 function executeUpgradeDelegate(address _multisig, address _delegateV3) external; /// @notice Burn stakes during initialization phase /// Can only be called by Manager or Owner /// @dev must be called after UpgradeDelegate is set as the token delegate /// @param tournamentID The index of the tournament /// @param roundID The index of the tournament round /// @param staker The address of the user /// @param tag The UTF8 character string used to identify the submission function destroyStake(uint256 tournamentID, uint256 roundID, address staker, bytes32 tag) external; } interface INMR { /* ERC20 Interface */ function transfer(address to, uint256 value) external returns (bool); function approve(address spender, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); function totalSupply() external view returns (uint256); function balanceOf(address who) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); /* NMR Special Interface */ // used for user balance management function withdraw(address _from, address _to, uint256 _value) external returns(bool ok); // used for migrating active stakes function destroyStake(address _staker, bytes32 _tag, uint256 _tournamentID, uint256 _roundID) external returns (bool ok); // used for disabling token upgradability function createRound(uint256, uint256, uint256, uint256) external returns (bool ok); // used for upgrading the token delegate logic function createTournament(uint256 _newDelegate) external returns (bool ok); // used like burn(uint256) function mint(uint256 _value) external returns (bool ok); // used like burnFrom(address, uint256) function numeraiTransfer(address _to, uint256 _value) external returns (bool ok); // used to check if upgrade completed function contractUpgradable() external view returns (bool); function getTournament(uint256 _tournamentID) external view returns (uint256, uint256[] memory); function getRound(uint256 _tournamentID, uint256 _roundID) external view returns (uint256, uint256, uint256); function getStake(uint256 _tournamentID, uint256 _roundID, address _staker, bytes32 _tag) external view returns (uint256, uint256, bool, bool); function changeApproval(address _spender, uint256 _oldValue, uint256 _newValue) external returns (bool ok); } interface IErasureStake { function increaseStake(uint256 currentStake, uint256 amountToAdd) external; function reward(uint256 currentStake, uint256 amountToAdd) external; function punish(uint256 currentStake, uint256 punishment, bytes calldata message) external returns (uint256 cost); function releaseStake(uint256 currentStake, uint256 amountToRelease) external; } /** * @title Initializable * * @dev Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. */ contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool wasInitializing = initializing; initializing = true; initialized = true; _; initializing = wasInitializing; } /// @dev Returns true if and only if the function is running in the constructor function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. uint256 cs; assembly { cs := extcodesize(address) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; } /** * @title SafeMath * @dev Unsigned math operations with safety checks that revert on error. */ library SafeMath { /** * @dev Multiplies two unsigned integers, reverts on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, "SafeMath: division by zero"); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); uint256 c = a - b; return c; } /** * @dev Adds two unsigned integers, reverts on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0, "SafeMath: modulo by zero"); return a % b; } } /* TODO: Update eip165 interface * bytes4(keccak256('create(bytes)')) == 0xcf5ba53f * bytes4(keccak256('getInstanceType()')) == 0x18c2f4cf * bytes4(keccak256('getInstanceRegistry()')) == 0xa5e13904 * bytes4(keccak256('getImplementation()')) == 0xaaf10f42 * * => 0xcf5ba53f ^ 0x18c2f4cf ^ 0xa5e13904 ^ 0xaaf10f42 == 0xd88967b6 */ interface iFactory { event InstanceCreated(address indexed instance, address indexed creator, string initABI, bytes initData); function create(bytes calldata initData) external returns (address instance); function createSalty(bytes calldata initData, bytes32 salt) external returns (address instance); function getInitSelector() external view returns (bytes4 initSelector); function getInstanceRegistry() external view returns (address instanceRegistry); function getTemplate() external view returns (address template); function getSaltyInstance(bytes calldata, bytes32 salt) external view returns (address instance); function getNextInstance(bytes calldata) external view returns (address instance); function getInstanceCreator(address instance) external view returns (address creator); function getInstanceType() external view returns (bytes4 instanceType); function getInstanceCount() external view returns (uint256 count); function getInstance(uint256 index) external view returns (address instance); function getInstances() external view returns (address[] memory instances); function getPaginatedInstances(uint256 startIndex, uint256 endIndex) external view returns (address[] memory instances); } /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". */ contract Ownable is Initializable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ function initialize(address sender) public initializer { _owner = sender; emit OwnershipTransferred(address(0), _owner); } /** * @return the address of the owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner()); _; } /** * @return true if `msg.sender` is the owner of the contract. */ function isOwner() public view returns (bool) { return msg.sender == _owner; } /** * @dev Allows the current owner to relinquish control of the contract. * @notice Renouncing to ownership will leave the contract without an owner. * It will not be possible to call the functions with the `onlyOwner` * modifier anymore. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0)); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } uint256[50] private ______gap; } contract Manageable is Initializable, Ownable { address private _manager; event ManagementTransferred(address indexed previousManager, address indexed newManager); /** * @dev The Managable constructor sets the original `manager` of the contract to the sender * account. */ function initialize(address sender) initializer public { Ownable.initialize(sender); _manager = sender; emit ManagementTransferred(address(0), _manager); } /** * @return the address of the manager. */ function manager() public view returns (address) { return _manager; } /** * @dev Throws if called by any account other than the owner or manager. */ modifier onlyManagerOrOwner() { require(isManagerOrOwner()); _; } /** * @return true if `msg.sender` is the owner or manager of the contract. */ function isManagerOrOwner() public view returns (bool) { return (msg.sender == _manager || isOwner()); } /** * @dev Allows the current owner to transfer control of the contract to a newManager. * @param newManager The address to transfer management to. */ function transferManagement(address newManager) public onlyOwner { require(newManager != address(0)); emit ManagementTransferred(_manager, newManager); _manager = newManager; } uint256[50] private ______gap; } /** * @title Pausable * @dev Base contract which allows children to implement an emergency stop mechanism. * Modified from openzeppelin Pausable to simplify access control. */ contract Pausable is Initializable, Manageable { event Paused(address account); event Unpaused(address account); bool private _paused; /// @notice Initializer function called at time of deployment /// @param sender The address of the wallet to handle permission control function initialize(address sender) public initializer { Manageable.initialize(sender); _paused = false; } /** * @return true if the contract is paused, false otherwise. */ function paused() public view returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPaused() { require(!_paused, "contract is paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. */ modifier whenPaused() { require(_paused, "expected contract to be paused"); _; } /** * @dev called by the owner to pause, triggers stopped state */ function pause() public onlyManagerOrOwner whenNotPaused { _paused = true; emit Paused(msg.sender); } /** * @dev called by the owner to unpause, returns to normal state */ function unpause() public onlyOwner whenPaused { _paused = false; emit Unpaused(msg.sender); } uint256[50] private ______gap; } contract NumeraiErasureV1 is Initializable, Pausable { using SafeMath for uint256; event CreateStake( address indexed agreement, address indexed staker ); event CreateAndIncreaseStake( address indexed agreement, address indexed staker, uint256 amount ); event IncreaseStake( address indexed agreement, address indexed staker, uint256 oldStakeAmount, uint256 amountAdded ); event Reward( address indexed agreement, address indexed staker, uint256 oldStakeAmount, uint256 amountAdded ); event Punish( address indexed agreement, address indexed staker, uint256 oldStakeAmount, uint256 amountPunished, bytes message ); event ReleaseStake( address indexed agreement, address indexed staker, uint256 oldStakeAmount, uint256 amountReleased ); event ResolveAndReleaseStake( address indexed agreement, address indexed staker, uint256 oldStakeAmount, uint256 amountReleased, uint256 amountStakeChanged, bool isReward ); // set the address of the NMR token as a constant (stored in runtime code) address private constant _TOKEN = address( 0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671 ); // set the address of the relay as a constant (stored in runtime code) address private constant _RELAY = address( 0xB17dF4a656505570aD994D023F632D48De04eDF2 ); /// @notice Initializer function called at time of deployment /// @param _owner The address of the wallet to handle permission control function initialize( address _owner ) public initializer { // initialize the contract's ownership. Pausable.initialize(_owner); } ///////////////////////////// // Fund Recovery Functions // ///////////////////////////// /// @notice Recover the ETH sent to this contract address /// Can only be called by the owner /// @param recipient The address of the recipient function recoverETH(address payable recipient) public onlyOwner { recipient.transfer(address(this).balance); } /// @notice Recover the NMR sent to this address /// Can only be called by the owner /// @param recipient The address of the recipient function recoverNMR(address payable recipient) public onlyOwner { uint256 balance = INMR(_TOKEN).balanceOf(address(this)); require(INMR(_TOKEN).transfer(recipient, balance), "transfer failed"); } //////////////////////// // Internal Functions // //////////////////////// function _approveNMR(address agreement, uint256 amountToAdd) internal { uint256 oldAllowance = INMR(_TOKEN).allowance(address(this), agreement); uint256 newAllowance = oldAllowance.add(amountToAdd); require(INMR(_TOKEN).changeApproval(agreement, oldAllowance, newAllowance), "Failed to approve"); } /////////////////// // NMR Functions // /////////////////// /// @notice Transfer NMR on behalf of a Numerai user /// Can only be called by Numerai /// @dev Calls the NMR token contract through the relay contract /// Can only be used on the first 1 million ethereum addresses. /// @param from The user address /// @param to The recipient address /// @param value The amount of NMR in wei function withdraw( address from, address to, uint256 value ) public onlyManagerOrOwner whenNotPaused { IRelay(_RELAY).withdraw(from, to, value); } /////////////////////// // Erasure Functions // /////////////////////// /// @notice Owned function to stake on Erasure agreement /// Can only be called by Numerai /// This function is intended as a bridge to allow for our custodied user accounts /// (ie. the first million addresses), to stake in an Erasure agreement. Erasure /// agreements assume an ERC-20 token, and the way we did custody doesn't quite fit /// in the normal ERC-20 way of doing things. Ideally, we would be able to call /// `changeApproval` on behalf of our custodied accounts, but that is unfortunately /// not possible. /// Instead what we have to do is `withdraw` the NMR into this contract and then call /// `changeApproval` on this contract before calling `increaseStake` on the Erasure /// agreement. The NMR is then taken from this contract to increase the stake. /// @param agreement The address of the agreement contract. Must conform to IErasureStake interface /// @param staker The address of the staker /// @param currentStake The amount of NMR in wei already staked on the agreement /// @param stakeAmount The amount of NMR in wei to incease the stake with this agreement function increaseStake( address agreement, address staker, uint256 currentStake, uint256 stakeAmount ) public onlyManagerOrOwner whenNotPaused { require(stakeAmount > 0, "Cannot stake zero NMR"); uint256 oldBalance = INMR(_TOKEN).balanceOf(address(this)); require(IRelay(_RELAY).withdraw(staker, address(this), stakeAmount), "Failed to withdraw"); _approveNMR(agreement, stakeAmount); IErasureStake(agreement).increaseStake(currentStake, stakeAmount); uint256 newBalance = INMR(_TOKEN).balanceOf(address(this)); require(oldBalance == newBalance, "Balance before/after did not match"); emit IncreaseStake(agreement, staker, currentStake, stakeAmount); } /// @notice Owned function to create an Erasure agreement stake /// @param factory The address of the agreement factory. Must conform to iFactory interface /// @param agreement The address of the agreement contract that will be created. Get this value by running factory.getSaltyInstance(...) /// @param staker The address of the staker /// @param callData The callData used to create the agreement /// @param salt The salt used to create the agreement function createStake( address factory, address agreement, address staker, bytes memory callData, bytes32 salt ) public onlyManagerOrOwner whenNotPaused { require(iFactory(factory).createSalty(callData, salt) == agreement, "Unexpected agreement address"); emit CreateStake(agreement, staker); } /// @notice Owned function to create an Erasure agreement stake /// @param factory The address of the agreement factory. Must conform to iFactory interface /// @param agreement The address of the agreement contract that will be created. Get this value by running factory.getSaltyInstance(...) /// @param staker The address of the staker /// @param stakeAmount The amount of NMR in wei to incease the stake with this agreement /// @param callData The callData used to create the agreement /// @param salt The salt used to create the agreement function createAndIncreaseStake( address factory, address agreement, address staker, uint256 stakeAmount, bytes memory callData, bytes32 salt ) public onlyManagerOrOwner whenNotPaused { createStake(factory, agreement, staker, callData, salt); increaseStake(agreement, staker, 0, stakeAmount); emit CreateAndIncreaseStake(agreement, staker, stakeAmount); } /// @notice Owned function to reward an Erasure agreement stake /// NMR tokens must be stored in this contract before this call. /// @param agreement The address of the agreement contract. Must conform to IErasureStake interface /// @param staker The address of the staker /// @param currentStake The amount of NMR in wei already staked on the agreement /// @param amountToAdd The amount of NMR in wei to incease the stake with this agreement function reward( address agreement, address staker, uint256 currentStake, uint256 amountToAdd ) public onlyManagerOrOwner whenNotPaused { require(amountToAdd > 0, "Cannot add zero NMR"); uint256 oldBalance = INMR(_TOKEN).balanceOf(address(this)); _approveNMR(agreement, amountToAdd); IErasureStake(agreement).reward(currentStake, amountToAdd); uint256 newBalance = INMR(_TOKEN).balanceOf(address(this)); require(oldBalance.sub(amountToAdd) == newBalance, "Balance before/after did not match"); emit Reward(agreement, staker, currentStake, amountToAdd); } /// @notice Owned function to punish an Erasure agreement stake /// @param agreement The address of the agreement contract. Must conform to IErasureStake interface /// @param staker The address of the staker /// @param currentStake The amount of NMR in wei already staked on the agreement /// @param punishment The amount of NMR in wei to punish the stake with this agreement function punish( address agreement, address staker, uint256 currentStake, uint256 punishment, bytes memory message ) public onlyManagerOrOwner whenNotPaused { require(punishment > 0, "Cannot punish zero NMR"); uint256 oldBalance = INMR(_TOKEN).balanceOf(address(this)); IErasureStake(agreement).punish(currentStake, punishment, message); uint256 newBalance = INMR(_TOKEN).balanceOf(address(this)); require(oldBalance == newBalance, "Balance before/after did not match"); emit Punish(agreement, staker, currentStake, punishment, message); } /// @notice Owned function to release an Erasure agreement stake /// @param agreement The address of the agreement contract. Must conform to IErasureStake interface /// @param staker The address of the staker /// @param currentStake The amount of NMR in wei already staked on the agreement /// @param amountToRelease The amount of NMR in wei to release back to the staker function releaseStake( address agreement, address staker, uint256 currentStake, uint256 amountToRelease ) public onlyManagerOrOwner whenNotPaused { require(amountToRelease > 0, "Cannot release zero NMR"); IErasureStake(agreement).releaseStake(currentStake, amountToRelease); emit ReleaseStake(agreement, staker, currentStake, amountToRelease); } /// @notice Owned function to resolve and then release an Erasure agreement stake /// @param agreement The address of the agreement contract. Must conform to IErasureStake interface /// @param staker The address of the staker /// @param currentStake The amount of NMR in wei already staked on the agreement /// @param amountToRelease The amount of NMR in wei to release back to the staker /// @param amountToChangeStake The amount of NMR to change the stake with /// @param isReward Boolean, if true then reward, else punish function resolveAndReleaseStake( address agreement, address staker, uint256 currentStake, uint256 amountToRelease, uint256 amountToChangeStake, bool isReward ) public onlyManagerOrOwner whenNotPaused { require(amountToRelease != 0, "Cannot release with zero NMR"); uint256 newStake = currentStake; if (amountToChangeStake != 0) { if(isReward) { reward(agreement, staker, currentStake, amountToChangeStake); newStake = currentStake.add(amountToChangeStake); } else { punish(agreement, staker, currentStake, amountToChangeStake, "punish before release"); newStake = currentStake.sub(amountToChangeStake); } } releaseStake(agreement, staker, newStake, amountToRelease); emit ResolveAndReleaseStake(agreement, staker, currentStake, amountToRelease, amountToChangeStake, isReward); } }
File 4 of 5: Relay
pragma solidity >=0.5.0 <0.6.0; interface INMR { /* ERC20 Interface */ function transfer(address to, uint256 value) external returns (bool); function approve(address spender, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); function totalSupply() external view returns (uint256); function balanceOf(address who) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); /* NMR Special Interface */ // used for user balance management function withdraw(address _from, address _to, uint256 _value) external returns(bool ok); // used for migrating active stakes function destroyStake(address _staker, bytes32 _tag, uint256 _tournamentID, uint256 _roundID) external returns (bool ok); // used for disabling token upgradability function createRound(uint256, uint256, uint256, uint256) external returns (bool ok); // used for upgrading the token delegate logic function createTournament(uint256 _newDelegate) external returns (bool ok); // used like burn(uint256) function mint(uint256 _value) external returns (bool ok); // used like burnFrom(address, uint256) function numeraiTransfer(address _to, uint256 _value) external returns (bool ok); // used to check if upgrade completed function contractUpgradable() external view returns (bool); function getTournament(uint256 _tournamentID) external view returns (uint256, uint256[] memory); function getRound(uint256 _tournamentID, uint256 _roundID) external view returns (uint256, uint256, uint256); function getStake(uint256 _tournamentID, uint256 _roundID, address _staker, bytes32 _tag) external view returns (uint256, uint256, bool, bool); } /** * @title Initializable * * @dev Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. */ contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool wasInitializing = initializing; initializing = true; initialized = true; _; initializing = wasInitializing; } /// @dev Returns true if and only if the function is running in the constructor function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. uint256 cs; assembly { cs := extcodesize(address) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; } /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". */ contract Ownable is Initializable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ function initialize(address sender) public initializer { _owner = sender; emit OwnershipTransferred(address(0), _owner); } /** * @return the address of the owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner()); _; } /** * @return true if `msg.sender` is the owner of the contract. */ function isOwner() public view returns (bool) { return msg.sender == _owner; } /** * @dev Allows the current owner to relinquish control of the contract. * @notice Renouncing to ownership will leave the contract without an owner. * It will not be possible to call the functions with the `onlyOwner` * modifier anymore. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0)); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } uint256[50] private ______gap; } contract Manageable is Initializable, Ownable { address private _manager; event ManagementTransferred(address indexed previousManager, address indexed newManager); /** * @dev The Managable constructor sets the original `manager` of the contract to the sender * account. */ function initialize(address sender) initializer public { Ownable.initialize(sender); _manager = sender; emit ManagementTransferred(address(0), _manager); } /** * @return the address of the manager. */ function manager() public view returns (address) { return _manager; } /** * @dev Throws if called by any account other than the owner or manager. */ modifier onlyManagerOrOwner() { require(isManagerOrOwner()); _; } /** * @return true if `msg.sender` is the owner or manager of the contract. */ function isManagerOrOwner() public view returns (bool) { return (msg.sender == _manager || isOwner()); } /** * @dev Allows the current owner to transfer control of the contract to a newManager. * @param newManager The address to transfer management to. */ function transferManagement(address newManager) public onlyOwner { require(newManager != address(0)); emit ManagementTransferred(_manager, newManager); _manager = newManager; } uint256[50] private ______gap; } contract Relay is Manageable { bool public active = true; bool private _upgraded; // set NMR token, 1M address, null address, burn address as constants address private constant _TOKEN = address( 0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671 ); address private constant _ONE_MILLION_ADDRESS = address( 0x00000000000000000000000000000000000F4240 ); address private constant _NULL_ADDRESS = address( 0x0000000000000000000000000000000000000000 ); address private constant _BURN_ADDRESS = address( 0x000000000000000000000000000000000000dEaD ); /// @dev Throws if the address does not match the required conditions. modifier isUser(address _user) { require( _user <= _ONE_MILLION_ADDRESS && _user != _NULL_ADDRESS && _user != _BURN_ADDRESS , "_from must be a user account managed by Numerai" ); _; } /// @dev Throws if called after the relay is disabled. modifier onlyActive() { require(active, "User account relay has been disabled"); _; } /// @notice Contructor function called at time of deployment /// @param _owner The initial owner and manager of the relay constructor(address _owner) public { require( address(this) == address(0xB17dF4a656505570aD994D023F632D48De04eDF2), "incorrect deployment address - check submitting account & nonce." ); Manageable.initialize(_owner); } /// @notice Transfer NMR on behalf of a Numerai user /// Can only be called by Manager or Owner /// @dev Can only be used on the first 1 million ethereum addresses /// @param _from The user address /// @param _to The recipient address /// @param _value The amount of NMR in wei function withdraw(address _from, address _to, uint256 _value) public onlyManagerOrOwner onlyActive isUser(_from) returns (bool ok) { require(INMR(_TOKEN).withdraw(_from, _to, _value)); return true; } /// @notice Burn the NMR sent to address 0 and burn address function burnZeroAddress() public { uint256 amtZero = INMR(_TOKEN).balanceOf(_NULL_ADDRESS); uint256 amtBurn = INMR(_TOKEN).balanceOf(_BURN_ADDRESS); require(INMR(_TOKEN).withdraw(_NULL_ADDRESS, address(this), amtZero)); require(INMR(_TOKEN).withdraw(_BURN_ADDRESS, address(this), amtBurn)); uint256 amtThis = INMR(_TOKEN).balanceOf(address(this)); _burn(amtThis); } /// @notice Permanantly disable the relay contract /// Can only be called by Owner function disable() public onlyOwner onlyActive { active = false; } /// @notice Permanantly disable token upgradability /// Can only be called by Owner function disableTokenUpgradability() public onlyOwner onlyActive { require(INMR(_TOKEN).createRound(uint256(0),uint256(0),uint256(0),uint256(0))); } /// @notice Upgrade the token delegate logic. /// Can only be called by Owner /// @param _newDelegate Address of the new delegate contract function changeTokenDelegate(address _newDelegate) public onlyOwner onlyActive { require(INMR(_TOKEN).createTournament(uint256(_newDelegate))); } /// @notice Get the address of the NMR token contract /// @return The address of the NMR token contract function token() external pure returns (address) { return _TOKEN; } /// @notice Internal helper function to burn NMR /// @dev If before the token upgrade, sends the tokens to address 0 /// If after the token upgrade, calls the repurposed mint function to burn /// @param _value The amount of NMR in wei function _burn(uint256 _value) internal { if (INMR(_TOKEN).contractUpgradable()) { require(INMR(_TOKEN).transfer(address(0), _value)); } else { require(INMR(_TOKEN).mint(_value), "burn not successful"); } } }
File 5 of 5: NumeraireDelegateV3
pragma solidity >=0.4.25 <0.5.0; /** * @title NMRSafeMath * @dev Unsigned math operations with safety checks that revert on error. */ library NMRSafeMath { /** * @dev Multiplies two unsigned integers, reverts on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b); return c; } /** * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a); uint256 c = a - b; return c; } /** * @dev Adds two unsigned integers, reverts on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a); return c; } /** * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0); return a % b; } } /* WARNING: This implementation is outdated and insecure */ /// @title Shareable /// @notice Multisig contract to manage access control contract Shareable { // TYPES // struct for the status of a pending operation. struct PendingState { uint yetNeeded; uint ownersDone; uint index; } // FIELDS // the number of owners that must confirm the same operation before it is run. uint public required; // list of owners address[256] owners; uint constant c_maxOwners = 250; // index on the list of owners to allow reverse lookup mapping(address => uint) ownerIndex; // the ongoing operations. mapping(bytes32 => PendingState) pendings; bytes32[] pendingsIndex; // EVENTS // this contract only has six types of events: it can accept a confirmation, in which case // we record owner and operation (hash) alongside it. event Confirmation(address owner, bytes32 operation); event Revoke(address owner, bytes32 operation); // MODIFIERS address thisContract = this; // simple single-sig function modifier. modifier onlyOwner { if (isOwner(msg.sender)) _; } // multi-sig function modifier: the operation must have an intrinsic hash in order // that later attempts can be realised as the same underlying operation and // thus count as confirmations. modifier onlyManyOwners(bytes32 _operation) { if (confirmAndCheck(_operation)) _; } // CONSTRUCTOR // constructor is given number of sigs required to do protected "onlymanyowners" transactions // as well as the selection of addresses capable of confirming them. function Shareable(address[] _owners, uint _required) { owners[1] = msg.sender; ownerIndex[msg.sender] = 1; for (uint i = 0; i < _owners.length; ++i) { owners[2 + i] = _owners[i]; ownerIndex[_owners[i]] = 2 + i; } if (required > owners.length) throw; required = _required; } // new multisig is given number of sigs required to do protected "onlymanyowners" transactions // as well as the selection of addresses capable of confirming them. // take all new owners as an array /* WARNING: This function contains a security vulnerability. This method does not clear the `owners` array and the `ownerIndex` mapping before updating the owner addresses. If the new array of owner addresses is shorter than the existing array of owner addresses, some of the existing owners will retain ownership. The fix implemented in NumeraireDelegateV2 successfully mitigates this bug by allowing new owners to remove the old owners from the `ownerIndex` mapping using a special transaction. Note that the old owners are not be removed from the `owners` array and that if the special transaction is incorectly crafted, it may result in fatal error to the multisig functionality. */ function changeShareable(address[] _owners, uint _required) onlyManyOwners(sha3(msg.data)) { for (uint i = 0; i < _owners.length; ++i) { owners[1 + i] = _owners[i]; ownerIndex[_owners[i]] = 1 + i; } if (required > owners.length) throw; required = _required; } // METHODS // Revokes a prior confirmation of the given operation function revoke(bytes32 _operation) external { uint index = ownerIndex[msg.sender]; // make sure they're an owner if (index == 0) return; uint ownerIndexBit = 2**index; var pending = pendings[_operation]; if (pending.ownersDone & ownerIndexBit > 0) { pending.yetNeeded++; pending.ownersDone -= ownerIndexBit; Revoke(msg.sender, _operation); } } // Gets an owner by 0-indexed position (using numOwners as the count) function getOwner(uint ownerIndex) external constant returns (address) { return address(owners[ownerIndex + 1]); } function isOwner(address _addr) constant returns (bool) { return ownerIndex[_addr] > 0; } function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool) { var pending = pendings[_operation]; uint index = ownerIndex[_owner]; // make sure they're an owner if (index == 0) return false; // determine the bit to set for this owner. uint ownerIndexBit = 2**index; return !(pending.ownersDone & ownerIndexBit == 0); } // INTERNAL METHODS function confirmAndCheck(bytes32 _operation) internal returns (bool) { // determine what index the present sender is: uint index = ownerIndex[msg.sender]; // make sure they're an owner if (index == 0) return; var pending = pendings[_operation]; // if we're not yet working on this operation, switch over and reset the confirmation status. if (pending.yetNeeded == 0) { // reset count of confirmations needed. pending.yetNeeded = required; // reset which owners have confirmed (none) - set our bitmap to 0. pending.ownersDone = 0; pending.index = pendingsIndex.length++; pendingsIndex[pending.index] = _operation; } // determine the bit to set for this owner. uint ownerIndexBit = 2**index; // make sure we (the message sender) haven't confirmed this operation previously. if (pending.ownersDone & ownerIndexBit == 0) { Confirmation(msg.sender, _operation); // ok - check if count is enough to go ahead. if (pending.yetNeeded <= 1) { // enough confirmations: reset and run interior. delete pendingsIndex[pendings[_operation].index]; delete pendings[_operation]; return true; } else { // not enough: record that this owner in particular confirmed. pending.yetNeeded--; pending.ownersDone |= ownerIndexBit; } } } function clearPending() internal { uint length = pendingsIndex.length; for (uint i = 0; i < length; ++i) if (pendingsIndex[i] != 0) delete pendings[pendingsIndex[i]]; delete pendingsIndex; } } /// @title Safe /// @notice Utility functions for safe data manipulations contract Safe { /// @dev Add two numbers without overflow /// @param a Uint number /// @param b Uint number /// @return result function safeAdd(uint a, uint b) internal returns (uint) { uint c = a + b; assert(c >= a && c >= b); return c; } /// @dev Substract two numbers without underflow /// @param a Uint number /// @param b Uint number /// @return result function safeSubtract(uint a, uint b) internal returns (uint) { uint c = a - b; assert(b <= a && c <= a); return c; } /// @dev Multiply two numbers without overflow /// @param a Uint number /// @param b Uint number /// @return result function safeMultiply(uint a, uint b) internal returns (uint) { uint c = a * b; assert(a == 0 || (c / a) == b); return c; } /// @dev Convert uint256 to uint128 without concatenating /// @param a Uint number /// @return result function shrink128(uint a) internal returns (uint128) { assert(a < 0x100000000000000000000000000000000); return uint128(a); } /// @dev Prevent short address attack /// @param numWords Uint length of calldata in bytes32 words modifier onlyPayloadSize(uint numWords) { assert(msg.data.length == numWords * 32 + 4); _; } /// @dev Fallback function to allow ETH to be received function () payable { } } /// @title StoppableShareable /// @notice Extend the Shareable multisig with ability to pause desired functions contract StoppableShareable is Shareable { bool public stopped; bool public stoppable = true; modifier stopInEmergency { if (!stopped) _; } modifier onlyInEmergency { if (stopped) _; } function StoppableShareable(address[] _owners, uint _required) Shareable(_owners, _required) { } /// @notice Trigger paused state /// @dev Can only be called by an owner function emergencyStop() external onlyOwner { assert(stoppable); stopped = true; } /// @notice Return to unpaused state /// @dev Can only be called by the multisig function release() external onlyManyOwners(sha3(msg.data)) { assert(stoppable); stopped = false; } /// @notice Disable ability to pause the contract /// @dev Can only be called by the multisig function disableStopping() external onlyManyOwners(sha3(msg.data)) { stoppable = false; } } /// @title NumeraireShared /// @notice Token and tournament storage layout contract NumeraireShared is Safe { address public numerai = this; // Cap the total supply and the weekly supply uint256 public supply_cap = 21000000e18; // 21 million uint256 public weekly_disbursement = 96153846153846153846153; uint256 public initial_disbursement; uint256 public deploy_time; uint256 public total_minted; // ERC20 requires totalSupply, balanceOf, and allowance uint256 public totalSupply; mapping (address => uint256) public balanceOf; mapping (address => mapping (address => uint256)) public allowance; mapping (uint => Tournament) public tournaments; // tournamentID struct Tournament { uint256 creationTime; uint256[] roundIDs; mapping (uint256 => Round) rounds; // roundID } struct Round { uint256 creationTime; uint256 endTime; uint256 resolutionTime; mapping (address => mapping (bytes32 => Stake)) stakes; // address of staker } // The order is important here because of its packing characteristics. // Particularly, `amount` and `confidence` are in the *same* word, so // Solidity can update both at the same time (if the optimizer can figure // out that you're updating both). This makes `stake()` cheap. struct Stake { uint128 amount; // Once the stake is resolved, this becomes 0 uint128 confidence; bool successful; bool resolved; } // Generates a public event on the blockchain to notify clients event Mint(uint256 value); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); event Staked(address indexed staker, bytes32 tag, uint256 totalAmountStaked, uint256 confidence, uint256 indexed tournamentID, uint256 indexed roundID); event RoundCreated(uint256 indexed tournamentID, uint256 indexed roundID, uint256 endTime, uint256 resolutionTime); event TournamentCreated(uint256 indexed tournamentID); event StakeDestroyed(uint256 indexed tournamentID, uint256 indexed roundID, address indexed stakerAddress, bytes32 tag); event StakeReleased(uint256 indexed tournamentID, uint256 indexed roundID, address indexed stakerAddress, bytes32 tag, uint256 etherReward); /// @notice Get the amount of NMR which can be minted /// @return uint256 Amount of NMR in wei function getMintable() constant returns (uint256) { return safeSubtract( safeAdd(initial_disbursement, safeMultiply(weekly_disbursement, safeSubtract(block.timestamp, deploy_time)) / 1 weeks), total_minted); } } /// @title NumeraireDelegateV3 /// @notice Delegate contract version 3 with the following functionality: /// 1) Disabled upgradability /// 2) Repurposed burn functions /// 3) User NMR balance management through the relay contract /// @dev Deployed at address /// @dev Set in tx /// @dev Retired in tx contract NumeraireDelegateV3 is StoppableShareable, NumeraireShared { address public delegateContract; bool public contractUpgradable; address[] public previousDelegates; string public standard; string public name; string public symbol; uint256 public decimals; // set the address of the relay as a constant (stored in runtime code) address private constant _RELAY = address( 0xB17dF4a656505570aD994D023F632D48De04eDF2 ); event DelegateChanged(address oldAddress, address newAddress); using NMRSafeMath for uint256; /* TODO: Can this contructor be removed completely? */ /// @dev Constructor called on deployment to initialize the delegate contract multisig /// @param _owners Array of owner address to control multisig /// @param _num_required Uint number of owners required for multisig transaction constructor(address[] _owners, uint256 _num_required) public StoppableShareable(_owners, _num_required) { require( address(this) == address(0x29F709e42C95C604BA76E73316d325077f8eB7b2), "incorrect deployment address - check submitting account & nonce." ); } ////////////////////////////// // Special Access Functions // ////////////////////////////// /// @notice Manage Numerai Tournament user balances /// @dev Can only be called by numerai through the relay contract /// @param _from User address from which to withdraw NMR /// @param _to Address where to deposit NMR /// @param _value Uint amount of NMR in wei to transfer /// @return ok True if the transfer succeeds function withdraw(address _from, address _to, uint256 _value) public returns(bool ok) { require(msg.sender == _RELAY); require(_to != address(0)); balanceOf[_from] = balanceOf[_from].sub(_value); balanceOf[_to] = balanceOf[_to].add(_value); emit Transfer(_from, _to, _value); return true; } /// @notice Repurposed function to allow the relay contract to disable token upgradability. /// @dev Can only be called by numerai through the relay contract /// @return ok True if the call is successful function createRound(uint256, uint256, uint256, uint256) public returns (bool ok) { require(msg.sender == _RELAY); require(contractUpgradable); contractUpgradable = false; return true; } /// @notice Repurposed function to allow the relay contract to upgrade the token. /// @dev Can only be called by numerai through the relay contract /// @param _newDelegate Address of the new delegate contract /// @return ok True if the call is successful function createTournament(uint256 _newDelegate) public returns (bool ok) { require(msg.sender == _RELAY); require(contractUpgradable); address newDelegate = address(_newDelegate); previousDelegates.push(delegateContract); emit DelegateChanged(delegateContract, newDelegate); delegateContract = newDelegate; return true; } ////////////////////////// // Repurposed Functions // ////////////////////////// /// @notice Repurposed function to implement token burn from the calling account /// @param _value Uint amount of NMR in wei to burn /// @return ok True if the burn succeeds function mint(uint256 _value) public returns (bool ok) { _burn(msg.sender, _value); return true; } /// @notice Repurposed function to implement token burn on behalf of an approved account /// @param _to Address from which to burn tokens /// @param _value Uint amount of NMR in wei to burn /// @return ok True if the burn succeeds function numeraiTransfer(address _to, uint256 _value) public returns (bool ok) { _burnFrom(_to, _value); return true; } //////////////////////// // Internal Functions // //////////////////////// /// @dev Internal function that burns an amount of the token of a given account. /// @param _account The account whose tokens will be burnt. /// @param _value The amount that will be burnt. function _burn(address _account, uint256 _value) internal { require(_account != address(0)); totalSupply = totalSupply.sub(_value); balanceOf[_account] = balanceOf[_account].sub(_value); emit Transfer(_account, address(0), _value); } /// @dev Internal function that burns an amount of the token of a given /// account, deducting from the sender's allowance for said account. Uses the /// internal burn function. /// Emits an Approval event (reflecting the reduced allowance). /// @param _account The account whose tokens will be burnt. /// @param _value The amount that will be burnt. function _burnFrom(address _account, uint256 _value) internal { allowance[_account][msg.sender] = allowance[_account][msg.sender].sub(_value); _burn(_account, _value); emit Approval(_account, msg.sender, allowance[_account][msg.sender]); } /////////////////////// // Trashed Functions // /////////////////////// /// @dev Disabled function no longer used function releaseStake(address, bytes32, uint256, uint256, uint256, bool) public pure returns (bool) { revert(); } /// @dev Disabled function no longer used function destroyStake(address, bytes32, uint256, uint256) public pure returns (bool) { revert(); } /// @dev Disabled function no longer used function stake(uint256, bytes32, uint256, uint256, uint256) public pure returns (bool) { revert(); } /// @dev Disabled function no longer used function stakeOnBehalf(address, uint256, bytes32, uint256, uint256, uint256) public pure returns (bool) { revert(); } }