Include Embark and .sol contracts
This commit is contained in:
parent
c8b4b29408
commit
38928ead32
|
@ -1,3 +1,11 @@
|
|||
.embark
|
||||
chains.json
|
||||
config/livenet/password
|
||||
config/production/password
|
||||
coverage
|
||||
embarkArtifacts
|
||||
node_modules
|
||||
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# Editor artifacts
|
||||
|
@ -26,3 +34,4 @@
|
|||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
module.exports = {
|
||||
// applies to all environments
|
||||
default: {
|
||||
enabled: true,
|
||||
rpcHost: "localhost", // HTTP-RPC server listening interface (default: "localhost")
|
||||
rpcPort: 8545, // HTTP-RPC server listening port (default: 8545)
|
||||
rpcCorsDomain: { // Domains from which to accept cross origin requests (browser enforced). This can also be a comma separated list
|
||||
auto: true, // When "auto" is true, Embark will automatically set the cors to the address of the webserver
|
||||
additionalCors: [] // Additional CORS domains to add to the list. If "auto" is false, only those will be added
|
||||
},
|
||||
wsRPC: true, // Enable the WS-RPC server
|
||||
wsOrigins: { // Same thing as "rpcCorsDomain", but for WS origins
|
||||
auto: true,
|
||||
additionalCors: []
|
||||
},
|
||||
wsHost: "localhost", // WS-RPC server listening interface (default: "localhost")
|
||||
wsPort: 8546 // WS-RPC server listening port (default: 8546)
|
||||
|
||||
// Accounts to use as node accounts
|
||||
// The order here corresponds to the order of `web3.eth.getAccounts`, so the first one is the `defaultAccount`
|
||||
/*,accounts: [
|
||||
{
|
||||
nodeAccounts: true, // Accounts use for the node
|
||||
numAddresses: "1", // Number of addresses/accounts (defaults to 1)
|
||||
password: "config/development/devpassword" // Password file for the accounts
|
||||
},
|
||||
// Below are additional accounts that will count as `nodeAccounts` in the `deployment` section of your contract config
|
||||
// Those will not be unlocked in the node itself
|
||||
{
|
||||
privateKey: "your_private_key"
|
||||
},
|
||||
{
|
||||
privateKeyFile: "path/to/file", // Either a keystore or a list of keys, separated by , or ;
|
||||
password: "passwordForTheKeystore" // Needed to decrypt the keystore file
|
||||
},
|
||||
{
|
||||
mnemonic: "12 word mnemonic",
|
||||
addressIndex: "0", // Optional. The index to start getting the address
|
||||
numAddresses: "1", // Optional. The number of addresses to get
|
||||
hdpath: "m/44'/60'/0'/0/" // Optional. HD derivation path
|
||||
}
|
||||
]*/
|
||||
},
|
||||
|
||||
// default environment, merges with the settings in default
|
||||
// assumed to be the intended environment by `embark run` and `embark blockchain`
|
||||
development: {
|
||||
ethereumClientName: "geth", // Can be geth or parity (default:geth)
|
||||
//ethereumClientBin: "geth", // path to the client binary. Useful if it is not in the global PATH
|
||||
networkType: "custom", // Can be: testnet, rinkeby, livenet or custom, in which case, it will use the specified networkId
|
||||
networkId: 1337, // Network id used when networkType is custom
|
||||
isDev: true, // Uses and ephemeral proof-of-authority network with a pre-funded developer account, mining enabled
|
||||
datadir: ".embark/development/datadir", // Data directory for the databases and keystore (Geth 1.8.15 and Parity 2.0.4 can use the same base folder, till now they does not conflict with each other)
|
||||
mineWhenNeeded: true, // Uses our custom script (if isDev is false) to mine only when needed
|
||||
nodiscover: true, // Disables the peer discovery mechanism (manual peer addition)
|
||||
maxpeers: 0, // Maximum number of network peers (network disabled if set to 0) (default: 25)
|
||||
proxy: true, // Proxy is used to present meaningful information about transactions
|
||||
targetGasLimit: 9000000, // Target gas limit sets the artificial target gas floor for the blocks to mine
|
||||
simulatorBlocktime: 0 // Specify blockTime in seconds for automatic mining. Default is 0 and no auto-mining.
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run privatenet" and/or "embark blockchain privatenet"
|
||||
privatenet: {
|
||||
networkType: "custom",
|
||||
networkId: 1337,
|
||||
isDev: false,
|
||||
datadir: ".embark/privatenet/datadir",
|
||||
// -- mineWhenNeeded --
|
||||
// This options is only valid when isDev is false.
|
||||
// Enabling this option uses our custom script to mine only when needed.
|
||||
// Embark creates a development account for you (using `geth account new`) and funds the account. This account can be used for
|
||||
// development (and even imported in to MetaMask). To enable correct usage, a password for this account must be specified
|
||||
// in the `account > password` setting below.
|
||||
// NOTE: once `mineWhenNeeded` is enabled, you must run an `embark reset` on your dApp before running
|
||||
// `embark blockchain` or `embark run` for the first time.
|
||||
mineWhenNeeded: true,
|
||||
// -- genesisBlock --
|
||||
// This option is only valid when mineWhenNeeded is true (which is only valid if isDev is false).
|
||||
// When enabled, geth uses POW to mine transactions as it would normally, instead of using POA as it does in --dev mode.
|
||||
// On the first `embark blockchain or embark run` after this option is enabled, geth will create a new chain with a
|
||||
// genesis block, which can be configured using the `genesisBlock` configuration option below.
|
||||
genesisBlock: "config/privatenet/genesis.json", // Genesis block to initiate on first creation of a development node
|
||||
nodiscover: true,
|
||||
maxpeers: 0,
|
||||
proxy: true,
|
||||
accounts: [
|
||||
{
|
||||
nodeAccounts: true,
|
||||
password: "config/privatenet/password" // Password to unlock the account
|
||||
}
|
||||
],
|
||||
targetGasLimit: 8000000,
|
||||
simulatorBlocktime: 0
|
||||
},
|
||||
|
||||
privateparitynet: {
|
||||
ethereumClientName: "parity",
|
||||
networkType: "custom",
|
||||
networkId: 1337,
|
||||
isDev: false,
|
||||
genesisBlock: "config/privatenet/genesis-parity.json", // Genesis block to initiate on first creation of a development node
|
||||
datadir: ".embark/privatenet/datadir",
|
||||
mineWhenNeeded: false,
|
||||
nodiscover: true,
|
||||
maxpeers: 0,
|
||||
proxy: true,
|
||||
accounts: [
|
||||
{
|
||||
nodeAccounts: true,
|
||||
password: "config/privatenet/password"
|
||||
}
|
||||
],
|
||||
targetGasLimit: 8000000,
|
||||
simulatorBlocktime: 0
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run testnet" and/or "embark blockchain testnet"
|
||||
testnet: {
|
||||
networkType: "testnet",
|
||||
syncMode: "light",
|
||||
accounts: [
|
||||
{
|
||||
nodeAccounts: true,
|
||||
password: "config/testnet/password"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run livenet" and/or "embark blockchain livenet"
|
||||
livenet: {
|
||||
networkType: "livenet",
|
||||
syncMode: "light",
|
||||
rpcCorsDomain: "http://localhost:8000",
|
||||
wsOrigins: "http://localhost:8000",
|
||||
accounts: [
|
||||
{
|
||||
nodeAccounts: true,
|
||||
password: "config/livenet/password"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// you can name an environment with specific settings and then specify with
|
||||
// "embark run custom_name" or "embark blockchain custom_name"
|
||||
//custom_name: {
|
||||
//}
|
||||
};
|
|
@ -0,0 +1,46 @@
|
|||
module.exports = {
|
||||
// default applies to all environments
|
||||
default: {
|
||||
enabled: true,
|
||||
provider: "whisper", // Communication provider. Currently, Embark only supports whisper
|
||||
available_providers: ["whisper"], // Array of available providers
|
||||
},
|
||||
|
||||
// default environment, merges with the settings in default
|
||||
// assumed to be the intended environment by `embark run`
|
||||
development: {
|
||||
connection: {
|
||||
host: "localhost", // Host of the blockchain node
|
||||
port: 8546, // Port of the blockchain node
|
||||
type: "ws" // Type of connection (ws or rpc)
|
||||
}
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run privatenet"
|
||||
privatenet: {
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run testnet"
|
||||
testnet: {
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run livenet"
|
||||
livenet: {
|
||||
},
|
||||
|
||||
// you can name an environment with specific settings and then specify with
|
||||
// "embark run custom_name"
|
||||
//custom_name: {
|
||||
//}
|
||||
// Use this section when you need a specific symmetric or private keys in whisper
|
||||
/*
|
||||
,keys: {
|
||||
symmetricKey: "your_symmetric_key",// Symmetric key for message decryption
|
||||
privateKey: "your_private_key" // Private Key to be used as a signing key and for message decryption
|
||||
}
|
||||
*/
|
||||
//}
|
||||
};
|
|
@ -0,0 +1,91 @@
|
|||
module.exports = {
|
||||
// default applies to all environments
|
||||
default: {
|
||||
// Blockchain node to deploy the contracts
|
||||
deployment: {
|
||||
host: "localhost", // Host of the blockchain node
|
||||
port: 8546, // Port of the blockchain node
|
||||
type: "ws" // Type of connection (ws or rpc),
|
||||
// Accounts to use instead of the default account to populate your wallet
|
||||
// The order here corresponds to the order of `web3.eth.getAccounts`, so the first one is the `defaultAccount`
|
||||
/*,accounts: [
|
||||
{
|
||||
privateKey: "your_private_key",
|
||||
balance: "5 ether" // You can set the balance of the account in the dev environment
|
||||
// Balances are in Wei, but you can specify the unit with its name
|
||||
},
|
||||
{
|
||||
privateKeyFile: "path/to/file", // Either a keystore or a list of keys, separated by , or ;
|
||||
password: "passwordForTheKeystore" // Needed to decrypt the keystore file
|
||||
},
|
||||
{
|
||||
mnemonic: "12 word mnemonic",
|
||||
addressIndex: "0", // Optional. The index to start getting the address
|
||||
numAddresses: "1", // Optional. The number of addresses to get
|
||||
hdpath: "m/44'/60'/0'/0/" // Optional. HD derivation path
|
||||
},
|
||||
{
|
||||
"nodeAccounts": true // Uses the Ethereum node's accounts
|
||||
}
|
||||
]*/
|
||||
},
|
||||
// order of connections the dapp should connect to
|
||||
dappConnection: [
|
||||
"$WEB3", // uses pre existing web3 object if available (e.g in Mist)
|
||||
"ws://localhost:8546",
|
||||
"http://localhost:8545"
|
||||
],
|
||||
|
||||
// Automatically call `ethereum.enable` if true.
|
||||
// If false, the following code must run before sending any transaction: `await EmbarkJS.enableEthereum();`
|
||||
// Default value is true.
|
||||
// dappAutoEnable: true,
|
||||
|
||||
gas: "auto",
|
||||
|
||||
// Strategy for the deployment of the contracts:
|
||||
// - implicit will try to deploy all the contracts located inside the contracts directory
|
||||
// or the directory configured for the location of the contracts. This is default one
|
||||
// when not specified
|
||||
// - explicit will only attempt to deploy the contracts that are explicitly specified inside the
|
||||
// contracts section.
|
||||
//strategy: 'implicit',
|
||||
|
||||
contracts: {
|
||||
|
||||
DAppStore: {
|
||||
args: [ 0x744d70fdbe2ba4cf95131626614a1763df805b9e ]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// default environment, merges with the settings in default
|
||||
// assumed to be the intended environment by `embark run`
|
||||
development: {
|
||||
dappConnection: [
|
||||
"ws://localhost:8546",
|
||||
"http://localhost:8545",
|
||||
"$WEB3" // uses pre existing web3 object if available (e.g in Mist)
|
||||
]
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run privatenet"
|
||||
privatenet: {
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run testnet"
|
||||
testnet: {
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run livenet"
|
||||
livenet: {
|
||||
},
|
||||
|
||||
// you can name an environment with specific settings and then specify with
|
||||
// "embark run custom_name" or "embark blockchain custom_name"
|
||||
//custom_name: {
|
||||
//}
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
dev_password
|
|
@ -0,0 +1,39 @@
|
|||
module.exports = {
|
||||
// default applies to all environments
|
||||
default: {
|
||||
enabled: true,
|
||||
available_providers: ["ens"],
|
||||
provider: "ens"
|
||||
},
|
||||
|
||||
// default environment, merges with the settings in default
|
||||
// assumed to be the intended environment by `embark run`
|
||||
development: {
|
||||
register: {
|
||||
rootDomain: "embark.eth",
|
||||
subdomains: {
|
||||
'status': '0x1a2f3b98e434c02363f3dac3174af93c1d690914'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run privatenet"
|
||||
privatenet: {
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run testnet"
|
||||
testnet: {
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run livenet"
|
||||
livenet: {
|
||||
},
|
||||
|
||||
// you can name an environment with specific settings and then specify with
|
||||
// "embark run custom_name" or "embark blockchain custom_name"
|
||||
//custom_name: {
|
||||
//}
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
// Embark has support for Flow enabled by default in its built-in webpack
|
||||
// config: type annotations will automatically be stripped out of DApp sources
|
||||
// without any additional configuration. Note that type checking is not
|
||||
// performed during builds.
|
||||
|
||||
// To enable Flow type checking refer to the preconfigured template:
|
||||
// https://github.com/embark-framework/embark-flow-template
|
||||
// A new DApp can be created from that template with:
|
||||
// embark new --template flow
|
||||
|
||||
module.exports = {
|
||||
typescript: false,
|
||||
// Setting `typescript: true` in this config will disable Flow support in
|
||||
// Embark's default webpack config and enable TypeScript support: .ts and
|
||||
// .tsx sources will automatically be transpiled into JavaScript without any
|
||||
// additional configuration. Note that type checking is not performed during
|
||||
// builds.
|
||||
|
||||
// To enable TypeScript type checking refer to the preconfigured template:
|
||||
// https://github.com/embark-framework/embark-typescript-template
|
||||
// A new DApp can be created from that template with:
|
||||
// embark new --template typescript
|
||||
enabled: true
|
||||
// Setting `enabled: false` in this config will disable Embark's built-in Webpack
|
||||
// pipeline. The developer will need to use a different frontend build tool, such as
|
||||
// `create-react-app` or Angular CLI to build their dapp
|
||||
};
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"config": {
|
||||
"homesteadBlock": 0,
|
||||
"byzantiumBlock": 0,
|
||||
"eip155Block": 0,
|
||||
"eip158Block": 0,
|
||||
"daoForkSupport": true
|
||||
},
|
||||
"nonce": "0x0000000000000042",
|
||||
"difficulty": "0x0",
|
||||
"alloc": {
|
||||
"0x3333333333333333333333333333333333333333": {"balance": "15000000000000000000"}
|
||||
},
|
||||
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase": "0x3333333333333333333333333333333333333333",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x",
|
||||
"gasLimit": "0x7a1200"
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
dev_password
|
|
@ -0,0 +1,59 @@
|
|||
module.exports = {
|
||||
// default applies to all environments
|
||||
default: {
|
||||
enabled: true,
|
||||
ipfs_bin: "ipfs",
|
||||
available_providers: ["ipfs"],
|
||||
upload: {
|
||||
provider: "ipfs",
|
||||
host: "localhost",
|
||||
port: 5001
|
||||
},
|
||||
dappConnection: [
|
||||
{
|
||||
provider: "ipfs",
|
||||
host: "localhost",
|
||||
port: 5001,
|
||||
getUrl: "http://localhost:8080/ipfs/"
|
||||
}
|
||||
]
|
||||
// Configuration to start Swarm in the same terminal as `embark run`
|
||||
/*,account: {
|
||||
address: "YOUR_ACCOUNT_ADDRESS", // Address of account accessing Swarm
|
||||
password: "PATH/TO/PASSWORD/FILE" // File containing the password of the account
|
||||
},
|
||||
swarmPath: "PATH/TO/SWARM/EXECUTABLE" // Path to swarm executable (default: swarm)*/
|
||||
},
|
||||
|
||||
// default environment, merges with the settings in default
|
||||
// assumed to be the intended environment by `embark run`
|
||||
development: {
|
||||
enabled: true,
|
||||
upload: {
|
||||
provider: "ipfs",
|
||||
host: "localhost",
|
||||
port: 5001,
|
||||
getUrl: "http://localhost:8080/ipfs/"
|
||||
}
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run privatenet"
|
||||
privatenet: {
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run testnet"
|
||||
testnet: {
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run livenet"
|
||||
livenet: {
|
||||
},
|
||||
|
||||
// you can name an environment with specific settings and then specify with
|
||||
// "embark run custom_name"
|
||||
//custom_name: {
|
||||
//}
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
test_password
|
|
@ -0,0 +1,6 @@
|
|||
module.exports = {
|
||||
enabled: true,
|
||||
host: "localhost",
|
||||
openBrowser: true,
|
||||
port: 8000
|
||||
};
|
|
@ -0,0 +1,305 @@
|
|||
pragma solidity ^0.5.1;
|
||||
|
||||
import "./token/MiniMeTokenInterface.sol";
|
||||
import "./token/ApproveAndCallFallBack.sol";
|
||||
import "./utils/SafeMath.sol";
|
||||
import "./utils/BancorFormula.sol";
|
||||
|
||||
contract DAppStore is ApproveAndCallFallBack, BancorFormula {
|
||||
using SafeMath for uint;
|
||||
|
||||
// Could be any EIP20/MiniMe token
|
||||
MiniMeTokenInterface SNT;
|
||||
|
||||
// Total SNT in circulation
|
||||
uint total;
|
||||
|
||||
// Parameter to calculate Max SNT any one DApp can stake
|
||||
uint ceiling;
|
||||
|
||||
// The max amount of tokens it is possible to stake, as a percentage of the total in circulation
|
||||
uint max;
|
||||
|
||||
// Decimal precision for this contract
|
||||
uint decimals;
|
||||
|
||||
// Prevents overflows in votes_minted
|
||||
uint safeMax;
|
||||
|
||||
// Whether we need more than an id param to identify arbitrary data must still be discussed.
|
||||
struct Data {
|
||||
address developer;
|
||||
bytes32 id;
|
||||
uint balance;
|
||||
uint rate;
|
||||
uint available;
|
||||
uint votes_minted;
|
||||
uint votes_cast;
|
||||
uint effective_balance;
|
||||
}
|
||||
|
||||
Data[] public dapps;
|
||||
mapping(bytes32 => uint) public id2index;
|
||||
|
||||
event DAppCreated(bytes32 indexed id, uint votes_mint, uint amount);
|
||||
event Upvote(bytes32 indexed id, uint newEffectiveBalance);
|
||||
event Downvote(bytes32 indexed id, uint newEffectiveBalance);
|
||||
event Withdraw(bytes32 indexed id, uint newEffectiveBalance);
|
||||
|
||||
constructor(MiniMeTokenInterface _SNT) public {
|
||||
SNT = _SNT;
|
||||
|
||||
total = 3470483788;
|
||||
|
||||
ceiling = 588; // 2 dec fixed pos, ie: 5 == 0.05, 588 == 5.88,
|
||||
|
||||
decimals = 1000000;
|
||||
|
||||
max = (total * ceiling) / decimals; // 4 decimal points for %, 2 because we only use 1/100th of total in circulation
|
||||
|
||||
safeMax = 98 * max / 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Anyone can create a DApp (i.e an arb piece of data this contract happens to care about).
|
||||
* @param _id bytes32 unique identifier.
|
||||
* @param _amount of tokens to stake on initial ranking.
|
||||
*/
|
||||
function createDApp(bytes32 _id, uint _amount) public {
|
||||
_createDApp(msg.sender, _id, _amount);
|
||||
}
|
||||
|
||||
function _createDApp(address _from, bytes32 _id, uint _amount) internal {
|
||||
require(_amount > 0, "You must spend some SNT to submit a ranking in order to avoid spam");
|
||||
require (_amount < safeMax, "You cannot stake more SNT than the ceiling dictates");
|
||||
require(SNT.allowance(_from, address(this)) >= _amount, "Not enough SNT allowance");
|
||||
require(SNT.transferFrom(_from, address(this), _amount), "Transfer failed");
|
||||
|
||||
uint dappIdx = dapps.length;
|
||||
|
||||
dapps.length++;
|
||||
|
||||
Data storage d = dapps[dappIdx];
|
||||
d.developer = msg.sender;
|
||||
d.id = _id;
|
||||
|
||||
uint precision;
|
||||
uint result;
|
||||
|
||||
d.balance = _amount;
|
||||
d.rate = decimals - (d.balance * decimals/max);
|
||||
d.available = d.balance * d.rate;
|
||||
|
||||
(result, precision) = BancorFormula.power(d.available, decimals, uint32(decimals), uint32(d.rate));
|
||||
|
||||
d.votes_minted = result >> precision;
|
||||
d.votes_cast = 0;
|
||||
d.effective_balance = _amount;
|
||||
|
||||
id2index[_id] = dappIdx;
|
||||
|
||||
emit DAppCreated(_id, d.votes_minted, d.effective_balance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Used in UI to display effect on ranking of user's donation
|
||||
* @param _id bytes32 unique identifier.
|
||||
* @param _amount of tokens to stake/"donate" to this DApp's ranking.
|
||||
* @return effect of donation on DApp's effective_balance
|
||||
*/
|
||||
function upvoteEffect(bytes32 _id, uint _amount) public view returns(uint effect) {
|
||||
uint dappIdx = id2index[_id];
|
||||
Data memory d = dapps[dappIdx];
|
||||
require(d.id == _id, "Error fetching correct data");
|
||||
require(d.balance + _amount < safeMax, "You cannot upvote by this much, try with a lower amount");
|
||||
|
||||
uint precision;
|
||||
uint result;
|
||||
|
||||
uint mBalance = d.balance + _amount;
|
||||
uint mRate = decimals - (mBalance * decimals/max);
|
||||
uint mAvailable = mBalance * mRate;
|
||||
|
||||
(result, precision) = BancorFormula.power(mAvailable, decimals, uint32(decimals), uint32(mRate));
|
||||
|
||||
uint mVMinted = result >> precision;
|
||||
uint mEBalance = mBalance - ((mVMinted*mRate)*(mAvailable/mVMinted));
|
||||
|
||||
return (mEBalance - d.effective_balance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sends SNT directly to the contract, not the developer. This gets added to the DApp's balance, no curve required.
|
||||
* @param _id bytes32 unique identifier.
|
||||
* @param _amount of tokens to stake on DApp's ranking. Used for upvoting + staking more.
|
||||
*/
|
||||
function upvote(bytes32 _id, uint _amount) public {
|
||||
_upvote(msg.sender, _id, _amount);
|
||||
}
|
||||
|
||||
function _upvote(address _from, bytes32 _id, uint _amount) internal {
|
||||
require(_amount > 0, "You must send some SNT in order to upvote");
|
||||
|
||||
uint dappIdx = id2index[_id];
|
||||
Data storage d = dapps[dappIdx];
|
||||
require(d.id == _id, "Error fetching correct data");
|
||||
|
||||
require(d.balance + _amount < safeMax, "You cannot upvote by this much, try with a lower amount");
|
||||
require(SNT.allowance(_from, address(this)) >= _amount, "Not enough SNT allowance");
|
||||
require(SNT.transferFrom(_from, address(this), _amount), "Transfer failed");
|
||||
|
||||
uint precision;
|
||||
uint result;
|
||||
|
||||
d.balance = d.balance + _amount;
|
||||
d.rate = decimals - (d.balance * decimals/max);
|
||||
d.available = d.balance * d.rate;
|
||||
|
||||
(result, precision) = BancorFormula.power(d.available, decimals, uint32(decimals), uint32(d.rate));
|
||||
|
||||
d.votes_minted = result >> precision;
|
||||
d.effective_balance = d.balance - ((d.votes_cast*d.rate)*(d.available/d.votes_minted));
|
||||
|
||||
emit Upvote(_id, d.effective_balance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Downvotes always remove 1% of the current ranking.
|
||||
* @param _id bytes32 unique identifier.
|
||||
* @return cost
|
||||
*/
|
||||
function downvoteCost(bytes32 _id) public view returns(uint b, uint v_r, uint c) {
|
||||
uint dappIdx = id2index[_id];
|
||||
Data memory d = dapps[dappIdx];
|
||||
require(d.id == _id, "Error fetching correct data");
|
||||
|
||||
uint balance_down_by = (d.effective_balance / 100);
|
||||
uint votes_required = (balance_down_by * d.votes_minted * d.rate) / d.available;
|
||||
uint cost = (d.available / (d.votes_minted - (d.votes_cast + votes_required))) * (votes_required / 1 / 10000);
|
||||
return (balance_down_by, votes_required, cost);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sends SNT directly to the developer and lower the DApp's effective balance by 1%
|
||||
* @param _id bytes32 unique identifier.
|
||||
*/
|
||||
function downvote(bytes32 _id) public {
|
||||
_downvote(msg.sender, _id);
|
||||
}
|
||||
|
||||
function _downvote(address _from, bytes32 _id) internal {
|
||||
uint dappIdx = id2index[_id];
|
||||
Data storage d = dapps[dappIdx];
|
||||
require(d.id == _id, "Error fetching correct data");
|
||||
|
||||
(uint b, uint v_r, uint c) = downvoteCost(_id);
|
||||
|
||||
require(SNT.allowance(_from, d.developer) >= c, "Not enough SNT allowance");
|
||||
require(SNT.transferFrom(_from, d.developer, c), "Transfer failed");
|
||||
|
||||
d.available = d.available - c;
|
||||
d.votes_cast = d.votes_cast + v_r;
|
||||
d.effective_balance = d.effective_balance - b;
|
||||
|
||||
emit Downvote(_id, d.effective_balance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Developers can withdraw an amount not more than what was available of the
|
||||
SNT they originally staked minus what they have already received back in downvotes.
|
||||
* @param _id bytes32 unique identifier.
|
||||
* @param _amount of tokens to withdraw from DApp's overall balance.
|
||||
*/
|
||||
function withdraw(bytes32 _id, uint _amount) public {
|
||||
uint dappIdx = id2index[_id];
|
||||
Data storage d = dapps[dappIdx];
|
||||
require(d.id == _id, "Error fetching correct data");
|
||||
|
||||
require(msg.sender == d.developer, "Only the developer can withdraw SNT staked on this data");
|
||||
require(_amount <= d.available, "You can only withdraw a percentage of the SNT staked, less what you have already received");
|
||||
|
||||
uint precision;
|
||||
uint result;
|
||||
|
||||
d.balance = d.balance - _amount;
|
||||
d.rate = decimals - (d.balance * decimals/max);
|
||||
d.available = d.balance * d.rate;
|
||||
|
||||
(result, precision) = BancorFormula.power(d.available, decimals, uint32(decimals), uint32(d.rate));
|
||||
|
||||
d.votes_minted = result >> precision;
|
||||
if (d.votes_cast > d.votes_minted) {
|
||||
d.votes_cast = d.votes_minted;
|
||||
}
|
||||
d.effective_balance = d.balance - ((d.votes_cast*d.rate)*(d.available/d.votes_minted));
|
||||
|
||||
SNT.transferFrom(address(this), d.developer, _amount);
|
||||
|
||||
emit Withdraw(_id, d.effective_balance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Support for "approveAndCall".
|
||||
* @param _from Who approved.
|
||||
* @param _amount Amount being approved, needs to be equal `_amount` or `cost`.
|
||||
* @param _token Token being approved, needs to be `SNT`.
|
||||
* @param _data Abi encoded data with selector of `register(bytes32,address,bytes32,bytes32)`.
|
||||
*/
|
||||
function receiveApproval(
|
||||
address _from,
|
||||
uint256 _amount,
|
||||
address _token,
|
||||
bytes memory _data
|
||||
)
|
||||
public
|
||||
{
|
||||
require(_token == address(SNT), "Wrong token");
|
||||
require(_token == address(msg.sender), "Wrong account");
|
||||
require(_data.length <= 132, "Incorrect data");
|
||||
|
||||
bytes4 sig;
|
||||
bytes32 id;
|
||||
uint256 amount;
|
||||
|
||||
(sig, id, amount) = abiDecodeRegister(_data);
|
||||
|
||||
require(_amount == amount, "Wrong amount");
|
||||
|
||||
// TODO: check these function sigs!
|
||||
if(sig == bytes4(0xe4bb1695)) {
|
||||
_createDApp(_from, id, amount);
|
||||
} else if(sig == bytes4(0xfaa5fd03)) {
|
||||
_downvote(_from, id);
|
||||
} else if(sig == bytes4(0x0643e21b)) {
|
||||
_upvote(_from, id, amount);
|
||||
} else {
|
||||
revert("Wrong method selector");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @dev Decodes abi encoded data with selector for "functionName(bytes32,uint256)".
|
||||
* @param _data Abi encoded data.
|
||||
* @return Decoded registry call.
|
||||
*/
|
||||
function abiDecodeRegister(
|
||||
bytes memory _data
|
||||
)
|
||||
private
|
||||
pure
|
||||
returns(
|
||||
bytes4 sig,
|
||||
bytes32 id,
|
||||
uint256 amount
|
||||
)
|
||||
{
|
||||
assembly {
|
||||
sig := mload(add(_data, add(0x20, 0)))
|
||||
id := mload(add(_data, 36))
|
||||
amount := mload(add(_data, 68))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
pragma solidity ^0.5.1;
|
||||
|
||||
contract ApproveAndCallFallBack {
|
||||
function receiveApproval(address from, uint256 _amount, address _token, bytes memory _data) public;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
pragma solidity ^0.5.1;
|
||||
|
||||
// Abstract contract for the full ERC 20 Token standard
|
||||
// https://github.com/ethereum/EIPs/issues/20
|
||||
|
||||
interface ERC20Token {
|
||||
|
||||
/**
|
||||
* @notice send `_value` token to `_to` from `msg.sender`
|
||||
* @param _to The address of the recipient
|
||||
* @param _value The amount of token to be transferred
|
||||
* @return Whether the transfer was successful or not
|
||||
*/
|
||||
function transfer(address _to, uint256 _value) external returns (bool success);
|
||||
|
||||
/**
|
||||
* @notice `msg.sender` approves `_spender` to spend `_value` tokens
|
||||
* @param _spender The address of the account able to transfer the tokens
|
||||
* @param _value The amount of tokens to be approved for transfer
|
||||
* @return Whether the approval was successful or not
|
||||
*/
|
||||
function approve(address _spender, uint256 _value) external returns (bool success);
|
||||
|
||||
/**
|
||||
* @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
|
||||
* @param _from The address of the sender
|
||||
* @param _to The address of the recipient
|
||||
* @param _value The amount of token to be transferred
|
||||
* @return Whether the transfer was successful or not
|
||||
*/
|
||||
function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);
|
||||
|
||||
/**
|
||||
* @param _owner The address from which the balance will be retrieved
|
||||
* @return The balance
|
||||
*/
|
||||
function balanceOf(address _owner) external view returns (uint256 balance);
|
||||
|
||||
/**
|
||||
* @param _owner The address of the account owning tokens
|
||||
* @param _spender The address of the account able to transfer the tokens
|
||||
* @return Amount of remaining tokens allowed to spent
|
||||
*/
|
||||
function allowance(address _owner, address _spender) external view returns (uint256 remaining);
|
||||
|
||||
/**
|
||||
* @notice return total supply of tokens
|
||||
*/
|
||||
function totalSupply() external view returns (uint256 supply);
|
||||
|
||||
event Transfer(address indexed _from, address indexed _to, uint256 _value);
|
||||
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
pragma solidity ^0.5.1;
|
||||
|
||||
import "./ERC20Token.sol";
|
||||
|
||||
|
||||
contract MiniMeTokenInterface is ERC20Token {
|
||||
|
||||
/**
|
||||
* @notice `msg.sender` approves `_spender` to send `_amount` tokens on
|
||||
* its behalf, and then a function is triggered in the contract that is
|
||||
* being approved, `_spender`. This allows users to use their tokens to
|
||||
* interact with contracts in one function call instead of two
|
||||
* @param _spender The address of the contract able to transfer the tokens
|
||||
* @param _amount The amount of tokens to be approved for transfer
|
||||
* @return True if the function call was successful
|
||||
*/
|
||||
function approveAndCall(
|
||||
address _spender,
|
||||
uint256 _amount,
|
||||
bytes calldata _extraData
|
||||
)
|
||||
external
|
||||
returns (bool success);
|
||||
|
||||
/**
|
||||
* @notice Creates a new clone token with the initial distribution being
|
||||
* this token at `_snapshotBlock`
|
||||
* @param _cloneTokenName Name of the clone token
|
||||
* @param _cloneDecimalUnits Number of decimals of the smallest unit
|
||||
* @param _cloneTokenSymbol Symbol of the clone token
|
||||
* @param _snapshotBlock Block when the distribution of the parent token is
|
||||
* copied to set the initial distribution of the new clone token;
|
||||
* if the block is zero than the actual block, the current block is used
|
||||
* @param _transfersEnabled True if transfers are allowed in the clone
|
||||
* @return The address of the new MiniMeToken Contract
|
||||
*/
|
||||
function createCloneToken(
|
||||
string memory _cloneTokenName,
|
||||
uint8 _cloneDecimalUnits,
|
||||
string memory _cloneTokenSymbol,
|
||||
uint _snapshotBlock,
|
||||
bool _transfersEnabled
|
||||
)
|
||||
public
|
||||
returns(address);
|
||||
|
||||
/**
|
||||
* @notice Generates `_amount` tokens that are assigned to `_owner`
|
||||
* @param _owner The address that will be assigned the new tokens
|
||||
* @param _amount The quantity of tokens generated
|
||||
* @return True if the tokens are generated correctly
|
||||
*/
|
||||
function generateTokens(
|
||||
address _owner,
|
||||
uint _amount
|
||||
)
|
||||
public
|
||||
returns (bool);
|
||||
|
||||
/**
|
||||
* @notice Burns `_amount` tokens from `_owner`
|
||||
* @param _owner The address that will lose the tokens
|
||||
* @param _amount The quantity of tokens to burn
|
||||
* @return True if the tokens are burned correctly
|
||||
*/
|
||||
function destroyTokens(
|
||||
address _owner,
|
||||
uint _amount
|
||||
)
|
||||
public
|
||||
returns (bool);
|
||||
|
||||
/**
|
||||
* @notice Enables token holders to transfer their tokens freely if true
|
||||
* @param _transfersEnabled True if transfers are allowed in the clone
|
||||
*/
|
||||
function enableTransfers(bool _transfersEnabled) public;
|
||||
|
||||
/**
|
||||
* @notice This method can be used by the controller to extract mistakenly
|
||||
* sent tokens to this contract.
|
||||
* @param _token The address of the token contract that you want to recover
|
||||
* set to 0 in case you want to extract ether.
|
||||
*/
|
||||
function claimTokens(address _token) public;
|
||||
|
||||
/**
|
||||
* @dev Queries the balance of `_owner` at a specific `_blockNumber`
|
||||
* @param _owner The address from which the balance will be retrieved
|
||||
* @param _blockNumber The block number when the balance is queried
|
||||
* @return The balance at `_blockNumber`
|
||||
*/
|
||||
function balanceOfAt(
|
||||
address _owner,
|
||||
uint _blockNumber
|
||||
)
|
||||
public
|
||||
view
|
||||
returns (uint);
|
||||
|
||||
/**
|
||||
* @notice Total amount of tokens at a specific `_blockNumber`.
|
||||
* @param _blockNumber The block number when the totalSupply is queried
|
||||
* @return The total amount of tokens at `_blockNumber`
|
||||
*/
|
||||
function totalSupplyAt(uint _blockNumber) public view returns(uint);
|
||||
|
||||
}
|
|
@ -0,0 +1,421 @@
|
|||
pragma solidity ^0.5.1;
|
||||
import './SafeMath.sol';
|
||||
|
||||
contract BancorFormula {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 private constant ONE = 1;
|
||||
uint32 private constant MAX_WEIGHT = 1000000;
|
||||
uint8 private constant MIN_PRECISION = 32;
|
||||
uint8 private constant MAX_PRECISION = 127;
|
||||
|
||||
/**
|
||||
Auto-generated via 'PrintIntScalingFactors.py'
|
||||
*/
|
||||
uint256 private constant FIXED_1 = 0x080000000000000000000000000000000;
|
||||
uint256 private constant FIXED_2 = 0x100000000000000000000000000000000;
|
||||
uint256 private constant MAX_NUM = 0x200000000000000000000000000000000;
|
||||
|
||||
/**
|
||||
Auto-generated via 'PrintLn2ScalingFactors.py'
|
||||
*/
|
||||
uint256 private constant LN2_NUMERATOR = 0x3f80fe03f80fe03f80fe03f80fe03f8;
|
||||
uint256 private constant LN2_DENOMINATOR = 0x5b9de1d10bf4103d647b0955897ba80;
|
||||
|
||||
/**
|
||||
Auto-generated via 'PrintFunctionOptimalLog.py' and 'PrintFunctionOptimalExp.py'
|
||||
*/
|
||||
uint256 private constant OPT_LOG_MAX_VAL = 0x15bf0a8b1457695355fb8ac404e7a79e3;
|
||||
uint256 private constant OPT_EXP_MAX_VAL = 0x800000000000000000000000000000000;
|
||||
|
||||
/**
|
||||
Auto-generated via 'PrintFunctionConstructor.py'
|
||||
*/
|
||||
uint256[128] private maxExpArray;
|
||||
constructor() public {
|
||||
// maxExpArray[ 0] = 0x6bffffffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 1] = 0x67ffffffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 2] = 0x637fffffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 3] = 0x5f6fffffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 4] = 0x5b77ffffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 5] = 0x57b3ffffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 6] = 0x5419ffffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 7] = 0x50a2ffffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 8] = 0x4d517fffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 9] = 0x4a233fffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 10] = 0x47165fffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 11] = 0x4429afffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 12] = 0x415bc7ffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 13] = 0x3eab73ffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 14] = 0x3c1771ffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 15] = 0x399e96ffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 16] = 0x373fc47fffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 17] = 0x34f9e8ffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 18] = 0x32cbfd5fffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 19] = 0x30b5057fffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 20] = 0x2eb40f9fffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 21] = 0x2cc8340fffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 22] = 0x2af09481ffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 23] = 0x292c5bddffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 24] = 0x277abdcdffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 25] = 0x25daf6657fffffffffffffffffffffffff;
|
||||
// maxExpArray[ 26] = 0x244c49c65fffffffffffffffffffffffff;
|
||||
// maxExpArray[ 27] = 0x22ce03cd5fffffffffffffffffffffffff;
|
||||
// maxExpArray[ 28] = 0x215f77c047ffffffffffffffffffffffff;
|
||||
// maxExpArray[ 29] = 0x1fffffffffffffffffffffffffffffffff;
|
||||
// maxExpArray[ 30] = 0x1eaefdbdabffffffffffffffffffffffff;
|
||||
// maxExpArray[ 31] = 0x1d6bd8b2ebffffffffffffffffffffffff;
|
||||
maxExpArray[ 32] = 0x1c35fedd14ffffffffffffffffffffffff;
|
||||
maxExpArray[ 33] = 0x1b0ce43b323fffffffffffffffffffffff;
|
||||
maxExpArray[ 34] = 0x19f0028ec1ffffffffffffffffffffffff;
|
||||
maxExpArray[ 35] = 0x18ded91f0e7fffffffffffffffffffffff;
|
||||
maxExpArray[ 36] = 0x17d8ec7f0417ffffffffffffffffffffff;
|
||||
maxExpArray[ 37] = 0x16ddc6556cdbffffffffffffffffffffff;
|
||||
maxExpArray[ 38] = 0x15ecf52776a1ffffffffffffffffffffff;
|
||||
maxExpArray[ 39] = 0x15060c256cb2ffffffffffffffffffffff;
|
||||
maxExpArray[ 40] = 0x1428a2f98d72ffffffffffffffffffffff;
|
||||
maxExpArray[ 41] = 0x13545598e5c23fffffffffffffffffffff;
|
||||
maxExpArray[ 42] = 0x1288c4161ce1dfffffffffffffffffffff;
|
||||
maxExpArray[ 43] = 0x11c592761c666fffffffffffffffffffff;
|
||||
maxExpArray[ 44] = 0x110a688680a757ffffffffffffffffffff;
|
||||
maxExpArray[ 45] = 0x1056f1b5bedf77ffffffffffffffffffff;
|
||||
maxExpArray[ 46] = 0x0faadceceeff8bffffffffffffffffffff;
|
||||
maxExpArray[ 47] = 0x0f05dc6b27edadffffffffffffffffffff;
|
||||
maxExpArray[ 48] = 0x0e67a5a25da4107fffffffffffffffffff;
|
||||
maxExpArray[ 49] = 0x0dcff115b14eedffffffffffffffffffff;
|
||||
maxExpArray[ 50] = 0x0d3e7a392431239fffffffffffffffffff;
|
||||
maxExpArray[ 51] = 0x0cb2ff529eb71e4fffffffffffffffffff;
|
||||
maxExpArray[ 52] = 0x0c2d415c3db974afffffffffffffffffff;
|
||||
maxExpArray[ 53] = 0x0bad03e7d883f69bffffffffffffffffff;
|
||||
maxExpArray[ 54] = 0x0b320d03b2c343d5ffffffffffffffffff;
|
||||
maxExpArray[ 55] = 0x0abc25204e02828dffffffffffffffffff;
|
||||
maxExpArray[ 56] = 0x0a4b16f74ee4bb207fffffffffffffffff;
|
||||
maxExpArray[ 57] = 0x09deaf736ac1f569ffffffffffffffffff;
|
||||
maxExpArray[ 58] = 0x0976bd9952c7aa957fffffffffffffffff;
|
||||
maxExpArray[ 59] = 0x09131271922eaa606fffffffffffffffff;
|
||||
maxExpArray[ 60] = 0x08b380f3558668c46fffffffffffffffff;
|
||||
maxExpArray[ 61] = 0x0857ddf0117efa215bffffffffffffffff;
|
||||
maxExpArray[ 62] = 0x07ffffffffffffffffffffffffffffffff;
|
||||
maxExpArray[ 63] = 0x07abbf6f6abb9d087fffffffffffffffff;
|
||||
maxExpArray[ 64] = 0x075af62cbac95f7dfa7fffffffffffffff;
|
||||
maxExpArray[ 65] = 0x070d7fb7452e187ac13fffffffffffffff;
|
||||
maxExpArray[ 66] = 0x06c3390ecc8af379295fffffffffffffff;
|
||||
maxExpArray[ 67] = 0x067c00a3b07ffc01fd6fffffffffffffff;
|
||||
maxExpArray[ 68] = 0x0637b647c39cbb9d3d27ffffffffffffff;
|
||||
maxExpArray[ 69] = 0x05f63b1fc104dbd39587ffffffffffffff;
|
||||
maxExpArray[ 70] = 0x05b771955b36e12f7235ffffffffffffff;
|
||||
maxExpArray[ 71] = 0x057b3d49dda84556d6f6ffffffffffffff;
|
||||
maxExpArray[ 72] = 0x054183095b2c8ececf30ffffffffffffff;
|
||||
maxExpArray[ 73] = 0x050a28be635ca2b888f77fffffffffffff;
|
||||
maxExpArray[ 74] = 0x04d5156639708c9db33c3fffffffffffff;
|
||||
maxExpArray[ 75] = 0x04a23105873875bd52dfdfffffffffffff;
|
||||
maxExpArray[ 76] = 0x0471649d87199aa990756fffffffffffff;
|
||||
maxExpArray[ 77] = 0x04429a21a029d4c1457cfbffffffffffff;
|
||||
maxExpArray[ 78] = 0x0415bc6d6fb7dd71af2cb3ffffffffffff;
|
||||
maxExpArray[ 79] = 0x03eab73b3bbfe282243ce1ffffffffffff;
|
||||
maxExpArray[ 80] = 0x03c1771ac9fb6b4c18e229ffffffffffff;
|
||||
maxExpArray[ 81] = 0x0399e96897690418f785257fffffffffff;
|
||||
maxExpArray[ 82] = 0x0373fc456c53bb779bf0ea9fffffffffff;
|
||||
maxExpArray[ 83] = 0x034f9e8e490c48e67e6ab8bfffffffffff;
|
||||
maxExpArray[ 84] = 0x032cbfd4a7adc790560b3337ffffffffff;
|
||||
maxExpArray[ 85] = 0x030b50570f6e5d2acca94613ffffffffff;
|
||||
maxExpArray[ 86] = 0x02eb40f9f620fda6b56c2861ffffffffff;
|
||||
maxExpArray[ 87] = 0x02cc8340ecb0d0f520a6af58ffffffffff;
|
||||
maxExpArray[ 88] = 0x02af09481380a0a35cf1ba02ffffffffff;
|
||||
maxExpArray[ 89] = 0x0292c5bdd3b92ec810287b1b3fffffffff;
|
||||
maxExpArray[ 90] = 0x0277abdcdab07d5a77ac6d6b9fffffffff;
|
||||
maxExpArray[ 91] = 0x025daf6654b1eaa55fd64df5efffffffff;
|
||||
maxExpArray[ 92] = 0x0244c49c648baa98192dce88b7ffffffff;
|
||||
maxExpArray[ 93] = 0x022ce03cd5619a311b2471268bffffffff;
|
||||
maxExpArray[ 94] = 0x0215f77c045fbe885654a44a0fffffffff;
|
||||
maxExpArray[ 95] = 0x01ffffffffffffffffffffffffffffffff;
|
||||
maxExpArray[ 96] = 0x01eaefdbdaaee7421fc4d3ede5ffffffff;
|
||||
maxExpArray[ 97] = 0x01d6bd8b2eb257df7e8ca57b09bfffffff;
|
||||
maxExpArray[ 98] = 0x01c35fedd14b861eb0443f7f133fffffff;
|
||||
maxExpArray[ 99] = 0x01b0ce43b322bcde4a56e8ada5afffffff;
|
||||
maxExpArray[100] = 0x019f0028ec1fff007f5a195a39dfffffff;
|
||||
maxExpArray[101] = 0x018ded91f0e72ee74f49b15ba527ffffff;
|
||||
maxExpArray[102] = 0x017d8ec7f04136f4e5615fd41a63ffffff;
|
||||
maxExpArray[103] = 0x016ddc6556cdb84bdc8d12d22e6fffffff;
|
||||
maxExpArray[104] = 0x015ecf52776a1155b5bd8395814f7fffff;
|
||||
maxExpArray[105] = 0x015060c256cb23b3b3cc3754cf40ffffff;
|
||||
maxExpArray[106] = 0x01428a2f98d728ae223ddab715be3fffff;
|
||||
maxExpArray[107] = 0x013545598e5c23276ccf0ede68034fffff;
|
||||
maxExpArray[108] = 0x01288c4161ce1d6f54b7f61081194fffff;
|
||||
maxExpArray[109] = 0x011c592761c666aa641d5a01a40f17ffff;
|
||||
maxExpArray[110] = 0x0110a688680a7530515f3e6e6cfdcdffff;
|
||||
maxExpArray[111] = 0x01056f1b5bedf75c6bcb2ce8aed428ffff;
|
||||
maxExpArray[112] = 0x00faadceceeff8a0890f3875f008277fff;
|
||||
maxExpArray[113] = 0x00f05dc6b27edad306388a600f6ba0bfff;
|
||||
maxExpArray[114] = 0x00e67a5a25da41063de1495d5b18cdbfff;
|
||||
maxExpArray[115] = 0x00dcff115b14eedde6fc3aa5353f2e4fff;
|
||||
maxExpArray[116] = 0x00d3e7a3924312399f9aae2e0f868f8fff;
|
||||
maxExpArray[117] = 0x00cb2ff529eb71e41582cccd5a1ee26fff;
|
||||
maxExpArray[118] = 0x00c2d415c3db974ab32a51840c0b67edff;
|
||||
maxExpArray[119] = 0x00bad03e7d883f69ad5b0a186184e06bff;
|
||||
maxExpArray[120] = 0x00b320d03b2c343d4829abd6075f0cc5ff;
|
||||
maxExpArray[121] = 0x00abc25204e02828d73c6e80bcdb1a95bf;
|
||||
maxExpArray[122] = 0x00a4b16f74ee4bb2040a1ec6c15fbbf2df;
|
||||
maxExpArray[123] = 0x009deaf736ac1f569deb1b5ae3f36c130f;
|
||||
maxExpArray[124] = 0x00976bd9952c7aa957f5937d790ef65037;
|
||||
maxExpArray[125] = 0x009131271922eaa6064b73a22d0bd4f2bf;
|
||||
maxExpArray[126] = 0x008b380f3558668c46c91c49a2f8e967b9;
|
||||
maxExpArray[127] = 0x00857ddf0117efa215952912839f6473e6;
|
||||
}
|
||||
|
||||
/**
|
||||
General Description:
|
||||
Determine a value of precision.
|
||||
Calculate an integer approximation of (_baseN / _baseD) ^ (_expN / _expD) * 2 ^ precision.
|
||||
Return the result along with the precision used.
|
||||
Detailed Description:
|
||||
Instead of calculating "base ^ exp", we calculate "e ^ (log(base) * exp)".
|
||||
The value of "log(base)" is represented with an integer slightly smaller than "log(base) * 2 ^ precision".
|
||||
The larger "precision" is, the more accurately this value represents the real value.
|
||||
However, the larger "precision" is, the more bits are required in order to store this value.
|
||||
And the exponentiation function, which takes "x" and calculates "e ^ x", is limited to a maximum exponent (maximum value of "x").
|
||||
This maximum exponent depends on the "precision" used, and it is given by "maxExpArray[precision] >> (MAX_PRECISION - precision)".
|
||||
Hence we need to determine the highest precision which can be used for the given input, before calling the exponentiation function.
|
||||
This allows us to compute "base ^ exp" with maximum accuracy and without exceeding 256 bits in any of the intermediate computations.
|
||||
This functions assumes that "_expN < 2 ^ 256 / log(MAX_NUM - 1)", otherwise the multiplication should be replaced with a "safeMul".
|
||||
*/
|
||||
function power(uint256 _baseN, uint256 _baseD, uint32 _expN, uint32 _expD) internal view returns (uint256, uint8) {
|
||||
require(_baseN < MAX_NUM);
|
||||
|
||||
uint256 baseLog;
|
||||
uint256 base = _baseN * FIXED_1 / _baseD;
|
||||
if (base < OPT_LOG_MAX_VAL) {
|
||||
baseLog = optimalLog(base);
|
||||
}
|
||||
else {
|
||||
baseLog = generalLog(base);
|
||||
}
|
||||
|
||||
uint256 baseLogTimesExp = baseLog * _expN / _expD;
|
||||
if (baseLogTimesExp < OPT_EXP_MAX_VAL) {
|
||||
return (optimalExp(baseLogTimesExp), MAX_PRECISION);
|
||||
}
|
||||
else {
|
||||
uint8 precision = findPositionInMaxExpArray(baseLogTimesExp);
|
||||
return (generalExp(baseLogTimesExp >> (MAX_PRECISION - precision), precision), precision);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Compute log(x / FIXED_1) * FIXED_1.
|
||||
This functions assumes that "x >= FIXED_1", because the output would be negative otherwise.
|
||||
*/
|
||||
function generalLog(uint256 x) internal pure returns (uint256) {
|
||||
uint256 res = 0;
|
||||
|
||||
// If x >= 2, then we compute the integer part of log2(x), which is larger than 0.
|
||||
if (x >= FIXED_2) {
|
||||
uint8 count = floorLog2(x / FIXED_1);
|
||||
x >>= count; // now x < 2
|
||||
res = count * FIXED_1;
|
||||
}
|
||||
|
||||
// If x > 1, then we compute the fraction part of log2(x), which is larger than 0.
|
||||
if (x > FIXED_1) {
|
||||
for (uint8 i = MAX_PRECISION; i > 0; --i) {
|
||||
x = (x * x) / FIXED_1; // now 1 < x < 4
|
||||
if (x >= FIXED_2) {
|
||||
x >>= 1; // now 1 < x < 2
|
||||
res += ONE << (i - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res * LN2_NUMERATOR / LN2_DENOMINATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
Compute the largest integer smaller than or equal to the binary logarithm of the input.
|
||||
*/
|
||||
function floorLog2(uint256 _n) internal pure returns (uint8) {
|
||||
uint8 res = 0;
|
||||
|
||||
if (_n < 256) {
|
||||
// At most 8 iterations
|
||||
while (_n > 1) {
|
||||
_n >>= 1;
|
||||
res += 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Exactly 8 iterations
|
||||
for (uint8 s = 128; s > 0; s >>= 1) {
|
||||
if (_n >= (ONE << s)) {
|
||||
_n >>= s;
|
||||
res |= s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
The global "maxExpArray" is sorted in descending order, and therefore the following statements are equivalent:
|
||||
- This function finds the position of [the smallest value in "maxExpArray" larger than or equal to "x"]
|
||||
- This function finds the highest position of [a value in "maxExpArray" larger than or equal to "x"]
|
||||
*/
|
||||
function findPositionInMaxExpArray(uint256 _x) internal view returns (uint8) {
|
||||
uint8 lo = MIN_PRECISION;
|
||||
uint8 hi = MAX_PRECISION;
|
||||
|
||||
while (lo + 1 < hi) {
|
||||
uint8 mid = (lo + hi) / 2;
|
||||
if (maxExpArray[mid] >= _x)
|
||||
lo = mid;
|
||||
else
|
||||
hi = mid;
|
||||
}
|
||||
|
||||
if (maxExpArray[hi] >= _x)
|
||||
return hi;
|
||||
if (maxExpArray[lo] >= _x)
|
||||
return lo;
|
||||
|
||||
require(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
This function can be auto-generated by the script 'PrintFunctionGeneralExp.py'.
|
||||
It approximates "e ^ x" via maclaurin summation: "(x^0)/0! + (x^1)/1! + ... + (x^n)/n!".
|
||||
It returns "e ^ (x / 2 ^ precision) * 2 ^ precision", that is, the result is upshifted for accuracy.
|
||||
The global "maxExpArray" maps each "precision" to "((maximumExponent + 1) << (MAX_PRECISION - precision)) - 1".
|
||||
The maximum permitted value for "x" is therefore given by "maxExpArray[precision] >> (MAX_PRECISION - precision)".
|
||||
*/
|
||||
function generalExp(uint256 _x, uint8 _precision) internal pure returns (uint256) {
|
||||
uint256 xi = _x;
|
||||
uint256 res = 0;
|
||||
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x3442c4e6074a82f1797f72ac0000000; // add x^02 * (33! / 02!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x116b96f757c380fb287fd0e40000000; // add x^03 * (33! / 03!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x045ae5bdd5f0e03eca1ff4390000000; // add x^04 * (33! / 04!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x00defabf91302cd95b9ffda50000000; // add x^05 * (33! / 05!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x002529ca9832b22439efff9b8000000; // add x^06 * (33! / 06!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x00054f1cf12bd04e516b6da88000000; // add x^07 * (33! / 07!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x0000a9e39e257a09ca2d6db51000000; // add x^08 * (33! / 08!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x000012e066e7b839fa050c309000000; // add x^09 * (33! / 09!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x000001e33d7d926c329a1ad1a800000; // add x^10 * (33! / 10!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x0000002bee513bdb4a6b19b5f800000; // add x^11 * (33! / 11!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x00000003a9316fa79b88eccf2a00000; // add x^12 * (33! / 12!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x0000000048177ebe1fa812375200000; // add x^13 * (33! / 13!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x0000000005263fe90242dcbacf00000; // add x^14 * (33! / 14!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x000000000057e22099c030d94100000; // add x^15 * (33! / 15!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x0000000000057e22099c030d9410000; // add x^16 * (33! / 16!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x00000000000052b6b54569976310000; // add x^17 * (33! / 17!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x00000000000004985f67696bf748000; // add x^18 * (33! / 18!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x000000000000003dea12ea99e498000; // add x^19 * (33! / 19!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x00000000000000031880f2214b6e000; // add x^20 * (33! / 20!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x000000000000000025bcff56eb36000; // add x^21 * (33! / 21!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x000000000000000001b722e10ab1000; // add x^22 * (33! / 22!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000001317c70077000; // add x^23 * (33! / 23!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x00000000000000000000cba84aafa00; // add x^24 * (33! / 24!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x00000000000000000000082573a0a00; // add x^25 * (33! / 25!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x00000000000000000000005035ad900; // add x^26 * (33! / 26!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x000000000000000000000002f881b00; // add x^27 * (33! / 27!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000001b29340; // add x^28 * (33! / 28!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x00000000000000000000000000efc40; // add x^29 * (33! / 29!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000000007fe0; // add x^30 * (33! / 30!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000000000420; // add x^31 * (33! / 31!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000000000021; // add x^32 * (33! / 32!)
|
||||
xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000000000001; // add x^33 * (33! / 33!)
|
||||
|
||||
return res / 0x688589cc0e9505e2f2fee5580000000 + _x + (ONE << _precision); // divide by 33! and then add x^1 / 1! + x^0 / 0!
|
||||
}
|
||||
|
||||
/**
|
||||
Return log(x / FIXED_1) * FIXED_1
|
||||
Input range: FIXED_1 <= x <= LOG_EXP_MAX_VAL - 1
|
||||
Auto-generated via 'PrintFunctionOptimalLog.py'
|
||||
Detailed description:
|
||||
- Rewrite the input as a product of natural exponents and a single residual r, such that 1 < r < 2
|
||||
- The natural logarithm of each (pre-calculated) exponent is the degree of the exponent
|
||||
- The natural logarithm of r is calculated via Taylor series for log(1 + x), where x = r - 1
|
||||
- The natural logarithm of the input is calculated by summing up the intermediate results above
|
||||
- For example: log(250) = log(e^4 * e^1 * e^0.5 * 1.021692859) = 4 + 1 + 0.5 + log(1 + 0.021692859)
|
||||
*/
|
||||
function optimalLog(uint256 x) internal pure returns (uint256) {
|
||||
uint256 res = 0;
|
||||
|
||||
uint256 y;
|
||||
uint256 z;
|
||||
uint256 w;
|
||||
|
||||
if (x >= 0xd3094c70f034de4b96ff7d5b6f99fcd8) {res += 0x40000000000000000000000000000000; x = x * FIXED_1 / 0xd3094c70f034de4b96ff7d5b6f99fcd8;} // add 1 / 2^1
|
||||
if (x >= 0xa45af1e1f40c333b3de1db4dd55f29a7) {res += 0x20000000000000000000000000000000; x = x * FIXED_1 / 0xa45af1e1f40c333b3de1db4dd55f29a7;} // add 1 / 2^2
|
||||
if (x >= 0x910b022db7ae67ce76b441c27035c6a1) {res += 0x10000000000000000000000000000000; x = x * FIXED_1 / 0x910b022db7ae67ce76b441c27035c6a1;} // add 1 / 2^3
|
||||
if (x >= 0x88415abbe9a76bead8d00cf112e4d4a8) {res += 0x08000000000000000000000000000000; x = x * FIXED_1 / 0x88415abbe9a76bead8d00cf112e4d4a8;} // add 1 / 2^4
|
||||
if (x >= 0x84102b00893f64c705e841d5d4064bd3) {res += 0x04000000000000000000000000000000; x = x * FIXED_1 / 0x84102b00893f64c705e841d5d4064bd3;} // add 1 / 2^5
|
||||
if (x >= 0x8204055aaef1c8bd5c3259f4822735a2) {res += 0x02000000000000000000000000000000; x = x * FIXED_1 / 0x8204055aaef1c8bd5c3259f4822735a2;} // add 1 / 2^6
|
||||
if (x >= 0x810100ab00222d861931c15e39b44e99) {res += 0x01000000000000000000000000000000; x = x * FIXED_1 / 0x810100ab00222d861931c15e39b44e99;} // add 1 / 2^7
|
||||
if (x >= 0x808040155aabbbe9451521693554f733) {res += 0x00800000000000000000000000000000; x = x * FIXED_1 / 0x808040155aabbbe9451521693554f733;} // add 1 / 2^8
|
||||
|
||||
z = y = x - FIXED_1;
|
||||
w = y * y / FIXED_1;
|
||||
res += z * (0x100000000000000000000000000000000 - y) / 0x100000000000000000000000000000000; z = z * w / FIXED_1; // add y^01 / 01 - y^02 / 02
|
||||
res += z * (0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - y) / 0x200000000000000000000000000000000; z = z * w / FIXED_1; // add y^03 / 03 - y^04 / 04
|
||||
res += z * (0x099999999999999999999999999999999 - y) / 0x300000000000000000000000000000000; z = z * w / FIXED_1; // add y^05 / 05 - y^06 / 06
|
||||
res += z * (0x092492492492492492492492492492492 - y) / 0x400000000000000000000000000000000; z = z * w / FIXED_1; // add y^07 / 07 - y^08 / 08
|
||||
res += z * (0x08e38e38e38e38e38e38e38e38e38e38e - y) / 0x500000000000000000000000000000000; z = z * w / FIXED_1; // add y^09 / 09 - y^10 / 10
|
||||
res += z * (0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b - y) / 0x600000000000000000000000000000000; z = z * w / FIXED_1; // add y^11 / 11 - y^12 / 12
|
||||
res += z * (0x089d89d89d89d89d89d89d89d89d89d89 - y) / 0x700000000000000000000000000000000; z = z * w / FIXED_1; // add y^13 / 13 - y^14 / 14
|
||||
res += z * (0x088888888888888888888888888888888 - y) / 0x800000000000000000000000000000000; // add y^15 / 15 - y^16 / 16
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
Return e ^ (x / FIXED_1) * FIXED_1
|
||||
Input range: 0 <= x <= OPT_EXP_MAX_VAL - 1
|
||||
Auto-generated via 'PrintFunctionOptimalExp.py'
|
||||
Detailed description:
|
||||
- Rewrite the input as a sum of binary exponents and a single residual r, as small as possible
|
||||
- The exponentiation of each binary exponent is given (pre-calculated)
|
||||
- The exponentiation of r is calculated via Taylor series for e^x, where x = r
|
||||
- The exponentiation of the input is calculated by multiplying the intermediate results above
|
||||
- For example: e^5.521692859 = e^(4 + 1 + 0.5 + 0.021692859) = e^4 * e^1 * e^0.5 * e^0.021692859
|
||||
*/
|
||||
function optimalExp(uint256 x) internal pure returns (uint256) {
|
||||
uint256 res = 0;
|
||||
|
||||
uint256 y;
|
||||
uint256 z;
|
||||
|
||||
z = y = x % 0x10000000000000000000000000000000; // get the input modulo 2^(-3)
|
||||
z = z * y / FIXED_1; res += z * 0x10e1b3be415a0000; // add y^02 * (20! / 02!)
|
||||
z = z * y / FIXED_1; res += z * 0x05a0913f6b1e0000; // add y^03 * (20! / 03!)
|
||||
z = z * y / FIXED_1; res += z * 0x0168244fdac78000; // add y^04 * (20! / 04!)
|
||||
z = z * y / FIXED_1; res += z * 0x004807432bc18000; // add y^05 * (20! / 05!)
|
||||
z = z * y / FIXED_1; res += z * 0x000c0135dca04000; // add y^06 * (20! / 06!)
|
||||
z = z * y / FIXED_1; res += z * 0x0001b707b1cdc000; // add y^07 * (20! / 07!)
|
||||
z = z * y / FIXED_1; res += z * 0x000036e0f639b800; // add y^08 * (20! / 08!)
|
||||
z = z * y / FIXED_1; res += z * 0x00000618fee9f800; // add y^09 * (20! / 09!)
|
||||
z = z * y / FIXED_1; res += z * 0x0000009c197dcc00; // add y^10 * (20! / 10!)
|
||||
z = z * y / FIXED_1; res += z * 0x0000000e30dce400; // add y^11 * (20! / 11!)
|
||||
z = z * y / FIXED_1; res += z * 0x000000012ebd1300; // add y^12 * (20! / 12!)
|
||||
z = z * y / FIXED_1; res += z * 0x0000000017499f00; // add y^13 * (20! / 13!)
|
||||
z = z * y / FIXED_1; res += z * 0x0000000001a9d480; // add y^14 * (20! / 14!)
|
||||
z = z * y / FIXED_1; res += z * 0x00000000001c6380; // add y^15 * (20! / 15!)
|
||||
z = z * y / FIXED_1; res += z * 0x000000000001c638; // add y^16 * (20! / 16!)
|
||||
z = z * y / FIXED_1; res += z * 0x0000000000001ab8; // add y^17 * (20! / 17!)
|
||||
z = z * y / FIXED_1; res += z * 0x000000000000017c; // add y^18 * (20! / 18!)
|
||||
z = z * y / FIXED_1; res += z * 0x0000000000000014; // add y^19 * (20! / 19!)
|
||||
z = z * y / FIXED_1; res += z * 0x0000000000000001; // add y^20 * (20! / 20!)
|
||||
res = res / 0x21c3677c82b40000 + y + FIXED_1; // divide by 20! and then add y^1 / 1! + y^0 / 0!
|
||||
|
||||
if ((x & 0x010000000000000000000000000000000) != 0) res = res * 0x1c3d6a24ed82218787d624d3e5eba95f9 / 0x18ebef9eac820ae8682b9793ac6d1e776; // multiply by e^2^(-3)
|
||||
if ((x & 0x020000000000000000000000000000000) != 0) res = res * 0x18ebef9eac820ae8682b9793ac6d1e778 / 0x1368b2fc6f9609fe7aceb46aa619baed4; // multiply by e^2^(-2)
|
||||
if ((x & 0x040000000000000000000000000000000) != 0) res = res * 0x1368b2fc6f9609fe7aceb46aa619baed5 / 0x0bc5ab1b16779be3575bd8f0520a9f21f; // multiply by e^2^(-1)
|
||||
if ((x & 0x080000000000000000000000000000000) != 0) res = res * 0x0bc5ab1b16779be3575bd8f0520a9f21e / 0x0454aaa8efe072e7f6ddbab84b40a55c9; // multiply by e^2^(+0)
|
||||
if ((x & 0x100000000000000000000000000000000) != 0) res = res * 0x0454aaa8efe072e7f6ddbab84b40a55c5 / 0x00960aadc109e7a3bf4578099615711ea; // multiply by e^2^(+1)
|
||||
if ((x & 0x200000000000000000000000000000000) != 0) res = res * 0x00960aadc109e7a3bf4578099615711d7 / 0x0002bf84208204f5977f9a8cf01fdce3d; // multiply by e^2^(+2)
|
||||
if ((x & 0x400000000000000000000000000000000) != 0) res = res * 0x0002bf84208204f5977f9a8cf01fdc307 / 0x0000003c6ab775dd0b95b4cbee7e65d11; // multiply by e^2^(+3)
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
pragma solidity ^0.5.1;
|
||||
|
||||
/*
|
||||
Library for basic math operations with overflow/underflow protection
|
||||
*/
|
||||
library SafeMath {
|
||||
/**
|
||||
@dev returns the sum of _x and _y, reverts if the calculation overflows
|
||||
@param _x value 1
|
||||
@param _y value 2
|
||||
@return sum
|
||||
*/
|
||||
function add(uint256 _x, uint256 _y) internal pure returns (uint256) {
|
||||
uint256 z = _x + _y;
|
||||
require(z >= _x);
|
||||
return z;
|
||||
}
|
||||
|
||||
/**
|
||||
@dev returns the difference of _x minus _y, reverts if the calculation underflows
|
||||
@param _x minuend
|
||||
@param _y subtrahend
|
||||
@return difference
|
||||
*/
|
||||
function sub(uint256 _x, uint256 _y) internal pure returns (uint256) {
|
||||
require(_x >= _y);
|
||||
return _x - _y;
|
||||
}
|
||||
|
||||
/**
|
||||
@dev returns the product of multiplying _x by _y, reverts if the calculation overflows
|
||||
@param _x factor 1
|
||||
@param _y factor 2
|
||||
@return product
|
||||
*/
|
||||
function mul(uint256 _x, uint256 _y) internal pure returns (uint256) {
|
||||
// gas optimization
|
||||
if (_x == 0)
|
||||
return 0;
|
||||
|
||||
uint256 z = _x * _y;
|
||||
require(z / _x == _y);
|
||||
return z;
|
||||
}
|
||||
|
||||
/**
|
||||
@dev Integer division of two numbers truncating the quotient, reverts on division by zero.
|
||||
@param _x dividend
|
||||
@param _y divisor
|
||||
@return quotient
|
||||
*/
|
||||
function div(uint256 _x, uint256 _y) internal pure returns (uint256) {
|
||||
require(_y > 0);
|
||||
uint256 c = _x / _y;
|
||||
|
||||
return c;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"contracts": ["contracts/**"],
|
||||
"buildDir": "build/",
|
||||
"config": "config/",
|
||||
"versions": {
|
||||
"web3": "1.0.0-beta",
|
||||
"solc": "0.5.1",
|
||||
"ipfs-api": "17.2.4"
|
||||
},
|
||||
"plugins": {
|
||||
"embarkjs-connector-web3": {}
|
||||
},
|
||||
"options": {
|
||||
"solc": {
|
||||
"optimize": true,
|
||||
"optimize-runs": 200
|
||||
}
|
||||
},
|
||||
"generationDir": "embarkArtifacts"
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "discover-dapps",
|
||||
"version": "0.1.0",
|
||||
"homepage": "https://status-im.github.io/discover-dapps",
|
||||
"version": "0.2.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"connected-react-router": "^6.3.2",
|
||||
|
@ -25,7 +26,8 @@
|
|||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject",
|
||||
"staging-deploy": "npm run build && aws s3 sync --acl public-read build s3://status-discover-dapps-staging/ --delete && rm -rf build"
|
||||
"predeploy": "npm run build",
|
||||
"deploy": "gh-pages -d build"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
@ -48,9 +50,11 @@
|
|||
"not op_mini all"
|
||||
],
|
||||
"devDependencies": {
|
||||
"embarkjs-connector-web3": "^4.0.0",
|
||||
"eslint-config-airbnb": "^17.1.0",
|
||||
"eslint-config-prettier": "^4.1.0",
|
||||
"eslint-plugin-prettier": "^3.0.1",
|
||||
"gh-pages": "^2.0.1",
|
||||
"husky": "^1.3.1",
|
||||
"lint-staged": "^8.1.5",
|
||||
"prettier": "^1.16.4"
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
// /*global contract, config, it, assert*/
|
||||
/*
|
||||
const SimpleStorage = require('Embark/contracts/SimpleStorage');
|
||||
|
||||
let accounts;
|
||||
|
||||
// For documentation please see https://embark.status.im/docs/contracts_testing.html
|
||||
config({
|
||||
//deployment: {
|
||||
// accounts: [
|
||||
// // you can configure custom accounts with a custom balance
|
||||
// // see https://embark.status.im/docs/contracts_testing.html#Configuring-accounts
|
||||
// ]
|
||||
//},
|
||||
contracts: {
|
||||
"SimpleStorage": {
|
||||
args: [100]
|
||||
}
|
||||
}
|
||||
}, (_err, web3_accounts) => {
|
||||
accounts = web3_accounts
|
||||
});
|
||||
|
||||
contract("SimpleStorage", function () {
|
||||
this.timeout(0);
|
||||
|
||||
it("should set constructor value", async function () {
|
||||
let result = await SimpleStorage.methods.storedData().call();
|
||||
assert.strictEqual(parseInt(result, 10), 100);
|
||||
});
|
||||
|
||||
it("set storage value", async function () {
|
||||
await SimpleStorage.methods.set(150).send();
|
||||
let result = await SimpleStorage.methods.get().call();
|
||||
assert.strictEqual(parseInt(result, 10), 150);
|
||||
});
|
||||
|
||||
it("should have account with balance", async function() {
|
||||
let balance = await web3.eth.getBalance(accounts[0]);
|
||||
assert.ok(parseInt(balance, 10) > 0);
|
||||
});
|
||||
}
|
||||
*/
|
Loading…
Reference in New Issue