Compare commits
304 Commits
feature/co
...
v5.4.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 87a468bc91 | |||
| 0734acbcbe | |||
| a45c8d14be | |||
| 61fe9add1b | |||
| 16141ed482 | |||
| 01ef37fd39 | |||
| 03b9f69d22 | |||
| dd76ebdc8d | |||
| e485bd90c0 | |||
| 1d89759c49 | |||
| d653b3715f | |||
| a05e2c75f3 | |||
| 124287b977 | |||
| 9906fde7ef | |||
| c7e1f118a6 | |||
| 1702c22084 | |||
| 32a123a825 | |||
| ac83573438 | |||
| 77c6c11800 | |||
| ca0a6f6ef9 | |||
| 4614c454a5 | |||
| 86bbe49c0b | |||
| d5322530c3 | |||
| 011d85447f | |||
| 9fd9dbc1b5 | |||
| b7d87cd8f2 | |||
| 6c8491e67b | |||
| 2623e71055 | |||
| ed0d420fd5 | |||
| 36666fd417 | |||
| 231d6e2477 | |||
| 6d6c6056f0 | |||
| b09c2830c8 | |||
| fc5a41123a | |||
| 107654ecca | |||
| 810a2eb5fd | |||
| 06a4e2173a | |||
| e55a209343 | |||
| 17bc4e7d8f | |||
| 4919605664 | |||
| f639e3aa19 | |||
| 84b4461ba6 | |||
| c4f8e9278e | |||
| 00905eb269 | |||
| 6a64842415 | |||
| 055d8bc0ef | |||
| 91779ccd03 | |||
| 516b8b31ac | |||
| ccd52f6ee5 | |||
| ffff09ab23 | |||
| 3df0831d9b | |||
| 27a746261c | |||
| 345b6bde82 | |||
| a86ea08bdf | |||
| e20bda73fb | |||
| 4c64aa7c2a | |||
| cf43bf9487 | |||
| 1a227ba67c | |||
| df7536589d | |||
| f0fe62f6d7 | |||
| 66fc992291 | |||
| 2a675c9417 | |||
| a3590d7c16 | |||
| 07a5ca847d | |||
| 37ce2fddde | |||
| 3a43284557 | |||
| 572848c04a | |||
| b6ce9dcfc8 | |||
| e7e8744ad2 | |||
| d2198dca61 | |||
| f9f2ef234e | |||
| a1f51428d0 | |||
| 555cb53c78 | |||
| ad74d30aa7 | |||
| 3568d3c141 | |||
| db566a581f | |||
| c69ebd0a62 | |||
| 5c375f764f | |||
| b04d572b9a | |||
| 1199b053fe | |||
| f06b21dfee | |||
| d643e5842c | |||
| a87d5326bf | |||
| c9fed46054 | |||
| 6f2097ed46 | |||
| 94d342ce63 | |||
| f984dec95a | |||
| 145b3ea766 | |||
| a80dfee5c5 | |||
| 4649de24c8 | |||
| 8539b56a48 | |||
| f59c37827a | |||
| 58db57ee45 | |||
| b64a7ca299 | |||
| 6f09ca8d13 | |||
| 6f53c8097e | |||
| 6b2ac15f56 | |||
| 359989f235 | |||
| 5894f6323b | |||
| 09b78e1e8f | |||
| 48c8f6b9b3 | |||
| 542ebaf3f3 | |||
| d82ffba75e | |||
| bdb2cee0c4 | |||
| cd45ce260f | |||
| 3a97983540 | |||
| 9714926e11 | |||
| 59614201b5 | |||
| e591742e40 | |||
| 791190f5e7 | |||
| 24b66daf2a | |||
| ad034d7712 | |||
| 375d8f3275 | |||
| 80dc787971 | |||
| 7967dc26f2 | |||
| c248725cc1 | |||
| 59135bf312 | |||
| 1d771c43e8 | |||
| 3cb94fb660 | |||
| 5820d71b2c | |||
| 4771c0c8a0 | |||
| 2a1ae117e8 | |||
| 8abc7ba77f | |||
| f696721918 | |||
| 00b58dec66 | |||
| 560315cbca | |||
| 24933f31a7 | |||
| b13bf6e8b0 | |||
| 8dcad88372 | |||
| dc6d2716aa | |||
| 80ad9db630 | |||
| 6f97c905d6 | |||
| 1b5f7ff95d | |||
| b5b12e22ce | |||
| fe811cdb12 | |||
| 42df6fe310 | |||
| c8805be054 | |||
| 764f63fc8c | |||
| f73ccedf42 | |||
| a9093c1c40 | |||
| e405644b1d | |||
| f6189bf910 | |||
| b6c06c289c | |||
| f405e39c04 | |||
| 1dbf3b5742 | |||
| 952b5153fd | |||
| d953141f52 | |||
| aa57d7c70b | |||
| 4c0bb879e8 | |||
| 9c5a517fb9 | |||
| b00ddda312 | |||
| 130e2a7797 | |||
| 27e5190e29 | |||
| b9c171884b | |||
| 4d2e0ea84b | |||
| 26d12ba239 | |||
| 1aae62e139 | |||
| f21c4cf9de | |||
| 6778b9060f | |||
| 4d36f78824 | |||
| 98ecf28262 | |||
| f5564fa923 | |||
| 096a9f3cea | |||
| 3d24835908 | |||
| 8cbef8458d | |||
| 9ca0580db6 | |||
| dfe38e7d21 | |||
| 377560805f | |||
| 65d9cf2a06 | |||
| b35dc2049b | |||
| 26c2710149 | |||
| cc24c27444 | |||
| f717968402 | |||
| 14d7fbd75e | |||
| 7eb1fedb42 | |||
| cbfe39f804 | |||
| a0e4f5410d | |||
| 766463b57b | |||
| 93e0b30b35 | |||
| 6510dca4b1 | |||
| 551edcfa72 | |||
| d58e2d560a | |||
| 99394e7f14 | |||
| 8ceab08bfc | |||
| 896db5e047 | |||
| d507d7b562 | |||
| 40c5d2a275 | |||
| a049f2eedb | |||
| b68b037000 | |||
| 181e6f3c23 | |||
| 19556349f6 | |||
| a1a1c5ef9f | |||
| afbd114a36 | |||
| db312dafbf | |||
| e4c3d9a468 | |||
| 5b49f82544 | |||
| 6088f30cd8 | |||
| f1e2c65b9e | |||
| 786f38cfb7 | |||
| 197a31b9e1 | |||
| 20acfc70e3 | |||
| 732dfe7b29 | |||
| 3ce8f41d32 | |||
| e0ff29d1c9 | |||
| 0ce62839e9 | |||
| cc2c9a7368 | |||
| 1abfc5a265 | |||
| 6b9466c348 | |||
| 9fffdbfb58 | |||
| 350dadec4d | |||
| 70b9edbcac | |||
| 92da07dca2 | |||
| 6fed81c0ed | |||
| 74e61e1393 | |||
| 6351db3057 | |||
| ed3e5dd4c4 | |||
| bd39d0f126 | |||
| 4c8ee69664 | |||
| eae8967322 | |||
| 9984ca66ba | |||
| 1b09a30646 | |||
| f40cc1d8ff | |||
| 91135dbc82 | |||
| adb7122a28 | |||
| ce446e530d | |||
| fedb10c5da | |||
| a24f80d44f | |||
| 61fa26da7a | |||
| 9512ba4334 | |||
| 65c129eafd | |||
| c2f763bec7 | |||
| c93a81808a | |||
| 51e5da414f | |||
| 3662f1ae24 | |||
| c568263fea | |||
| 38079d07db | |||
| 0cc67c2fad | |||
| a45be0021e | |||
| 4bd1aed197 | |||
| 94832d4d07 | |||
| 4f5ae01c5a | |||
| d6f99f57b7 | |||
| 901566d1ff | |||
| 5d4be8f176 | |||
| f9ab8b225a | |||
| dfa55516ec | |||
| b6f34ac9a5 | |||
| 258c6729b6 | |||
| b201642485 | |||
| 0686c79998 | |||
| 7e68dbf8c2 | |||
| f5973756c8 | |||
| 9cc237fbf4 | |||
| 3584a73c08 | |||
| 3c2cdf4376 | |||
| fbda45376e | |||
| cd7df3893e | |||
| e1fea4ed97 | |||
| 12341d1526 | |||
| 14b23ecdf1 | |||
| 1679afb9b4 | |||
| b03095e149 | |||
| 0d9b2d7d58 | |||
| e7affdb531 | |||
| 1594bf0e17 | |||
| 203199c268 | |||
| 116f69cb12 | |||
| 6c569239de | |||
| d687ff604e | |||
| c9a4b1decc | |||
| dae44cac70 | |||
| 6b8f718051 | |||
| 6d9a54b71c | |||
| 75d426f0cc | |||
| 7ce100e819 | |||
| 7216522d83 | |||
| 956f858620 | |||
| 8a7abba486 | |||
| c6c48f49d2 | |||
| db2e12c750 | |||
| 7dc75a19b5 | |||
| 926913da50 | |||
| a045702937 | |||
| b13b93122e | |||
| c23e7f2df8 | |||
| 7260544838 | |||
| da2f951bdb | |||
| 017073018f | |||
| fe1fa2e881 | |||
| c367c9cf6b | |||
| 52643da096 | |||
| ad5fe3ae77 | |||
| 418785059c | |||
| 89261d039a | |||
| 6949a5940a | |||
| ce5f5fb8d2 | |||
| 2e8d00bc2c | |||
| b1345b53f3 | |||
| 847f5a251c | |||
| 62a5cefd1a | |||
| 6378df7075 | |||
| bd2af6ed72 | |||
| 85032353ca | |||
| e2e9cd5c3b |
1
.eslintignore
Normal file
1
.eslintignore
Normal file
@@ -0,0 +1 @@
|
||||
/scripts/
|
||||
32
.eslintrc.js
Normal file
32
.eslintrc.js
Normal file
@@ -0,0 +1,32 @@
|
||||
module.exports = {
|
||||
'env': {
|
||||
'browser': true,
|
||||
'es6': true,
|
||||
'node': true
|
||||
},
|
||||
'extends': 'eslint:recommended',
|
||||
'globals': {
|
||||
'Atomics': 'readonly',
|
||||
'SharedArrayBuffer': 'readonly'
|
||||
},
|
||||
'parserOptions': {
|
||||
'ecmaVersion': 2018,
|
||||
'sourceType': 'module'
|
||||
},
|
||||
'rules': {
|
||||
'comma-dangle': ['error', {
|
||||
arrays: 'always-multiline',
|
||||
objects: 'always-multiline',
|
||||
imports: 'never',
|
||||
exports: 'never',
|
||||
functions: 'ignore',
|
||||
}],
|
||||
'eol-last': ['error', 'always'],
|
||||
semi: ['error', 'always'],
|
||||
'space-before-function-paren': ['error', {
|
||||
anonymous: 'never',
|
||||
named: 'always',
|
||||
asyncArrow: 'always',
|
||||
}],
|
||||
}
|
||||
}
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,3 +1,8 @@
|
||||
build
|
||||
flattened_contracts
|
||||
node_modules
|
||||
.ganache-db
|
||||
**/node_modules
|
||||
.ganache-db
|
||||
.tm_properties
|
||||
yarn-error.log
|
||||
.DS_Store
|
||||
|
||||
9
.solhint.json
Normal file
9
.solhint.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": [
|
||||
"solhint:default",
|
||||
"solhint:recommended"
|
||||
],
|
||||
"rules": {
|
||||
"indent": "2"
|
||||
}
|
||||
}
|
||||
19
.travis.yml
Normal file
19
.travis.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
language: node_js
|
||||
node_js:
|
||||
- "lts/*"
|
||||
|
||||
sudo: false
|
||||
dist: xenial
|
||||
|
||||
install:
|
||||
- npm install
|
||||
|
||||
script:
|
||||
- npm run lint:wrapper
|
||||
- npm run lint:contract-tests
|
||||
# - yarn lint:contracts
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
221
README.md
Normal file
221
README.md
Normal file
@@ -0,0 +1,221 @@
|
||||
[](https://www.npmjs.com/package/kredits-contracts)
|
||||
|
||||
# Kredits Contracts
|
||||
|
||||
This repository contains the Solidity smart contracts organized as
|
||||
[Aragon](https://hack.aragon.org/) apps and JavaScript API wrapper for [Kosmos
|
||||
Kredits](https://wiki.kosmos.org/Kredits).
|
||||
|
||||
It is based on [aragonOS](https://hack.aragon.org/docs/aragonos-intro.html) and
|
||||
follows the aragonOS conventions. Aragon itself uses the [Truffle
|
||||
framework](http://truffleframework.com/) for some things.
|
||||
|
||||
## Development
|
||||
|
||||
### Installation
|
||||
|
||||
All requirements are defined in `package.json`.
|
||||
|
||||
$ npm install
|
||||
|
||||
Each of the aragon apps are separate packages:
|
||||
|
||||
$ cd apps/[app]
|
||||
$ npm install
|
||||
|
||||
You can use `npm run install-all` to install all app dependencies at once.
|
||||
|
||||
### Local development chain
|
||||
|
||||
For local development it is recommended to use
|
||||
[ganache](http://truffleframework.com/ganache/) to run a local development
|
||||
chain. Using the ganache simulator no full Ethereum node is required.
|
||||
|
||||
We use the default aragon-cli devchain command to confgure and run a local
|
||||
development ganache.
|
||||
|
||||
$ npm run devchain (or aragon devchain --port 7545)
|
||||
|
||||
To clear/reset the chain use (e.g. if you run out of funds on your devchain)
|
||||
|
||||
$ npm run devchain -- --reset (or aragon devchain --port 7545 --reset)
|
||||
|
||||
We default to port 7545 for development to not get in conflict with the default
|
||||
Ethereum RPC port.
|
||||
|
||||
### Bootstrap
|
||||
|
||||
1. Run an Ethereum node and ipfs
|
||||
|
||||
$ npm run devchain
|
||||
$ ipfs daemon
|
||||
|
||||
2. Deploy each app to the devchain
|
||||
|
||||
(make sure you've run `npm install` for every app - see installation)
|
||||
$ npm run deploy:apps
|
||||
|
||||
3. Deploy a new KreditsKit and create a new DAO with the latest app versions
|
||||
|
||||
$ npm run deploy:kit
|
||||
$ npm run deploy:dao
|
||||
|
||||
4. Execute seeds to create demo contributors, contributons, etc. (optional)
|
||||
|
||||
$ npm run seeds
|
||||
|
||||
**Step 2-4 is also summarized in `npm run bootstrap`**
|
||||
|
||||
If you want to reset your local setup:
|
||||
|
||||
$ npm run reset // deploys a new kit and a new DAO
|
||||
$ npm run reset:hard // deploys all apps and does reset
|
||||
|
||||
## Contract architecture
|
||||
|
||||
Contracts are organized in independent apps (see `/apps`) and are developed and
|
||||
deployed independently. Each app has a version and can be "installed" on the
|
||||
Kredits DAO independently.
|
||||
|
||||

|
||||
|
||||
A DAO can be deployed using the `scripts/deploy-kit.js` script or with the
|
||||
`npm run deploy:dao` command. This deploys a new Kredits DAO, installs the
|
||||
latest app versions and sets the required permissions.
|
||||
|
||||
See each app in `/apps/*` for details.
|
||||
|
||||
|
||||
## Helper scripts
|
||||
|
||||
`scripts/` contains some helper scripts to interact with the contracts from the
|
||||
CLI. _At some point these should be moved into a real nice CLI._
|
||||
|
||||
To run these scripts use `truffle exec`. For example: `truffle exec
|
||||
scripts/add-proposal.js`.
|
||||
|
||||
Some scripts are also defined as npm script, see package.json.
|
||||
|
||||
### cli.js
|
||||
|
||||
Call any function on any contract:
|
||||
|
||||
$ truffle exec scripts/cli.js
|
||||
|
||||
### repl.js
|
||||
|
||||
Similar to cli.js but only provides a REPL with an initialized `kredits`
|
||||
instance.
|
||||
|
||||
$ truffle exec scripts/repl.js
|
||||
|
||||
### add-{contributor, contribution, proposal}.js
|
||||
|
||||
Script to add a new entries to the contracts using the JS wrapper
|
||||
|
||||
$ truffle exec scripts/add-{contributor, contribution, proposal}.js
|
||||
|
||||
### list-{contributors, contributions, proposals}.js
|
||||
|
||||
List contract entries
|
||||
|
||||
$ truffle exec scripts/list-{contributors, contributions, proposals}.js
|
||||
|
||||
### send-funds.js
|
||||
|
||||
Sends funds to an address. Helpful in development mode to for example fund a
|
||||
metamask account.
|
||||
|
||||
$ truffle exec scripts/send-funds.js
|
||||
|
||||
### seeds.js
|
||||
|
||||
Run seeds defined in `config/seeds.js`.
|
||||
|
||||
$ truffle exec scripts/seeds.js
|
||||
or
|
||||
$ npm run seeds
|
||||
|
||||
### current-address.js
|
||||
|
||||
Prints all known DAO addresses and the DAO address for the current network
|
||||
|
||||
$ truffle exec scripts/current-address.js
|
||||
or
|
||||
$ npm run dao:address
|
||||
|
||||
### deploy-kit.js
|
||||
|
||||
Deploys a new KreditsKit that allows to create a new DAO
|
||||
|
||||
$ truffle exec script/deploy-kit.js
|
||||
or
|
||||
$ npm run deploy:kit
|
||||
|
||||
`ENS` address is required as environment variable.
|
||||
`DAO_FACTORY` can optionally be set as environment variable. (see aragon)
|
||||
|
||||
### new-dao.js
|
||||
|
||||
Creates and configures a new DAO instance.
|
||||
|
||||
$ truffle exec script/new-dao.js
|
||||
or
|
||||
$ npm run deploy:dao
|
||||
|
||||
KreditsKit address is load from `lib/addresses/KreditsKit.json` or can be
|
||||
configured through the `KREDITS_KIT` environment variable.
|
||||
|
||||
### deploy-apps.sh
|
||||
|
||||
Runs `npm install` for each app and publishes a new version.
|
||||
|
||||
$ ./scripts/deploy-apps.sh
|
||||
or
|
||||
$ npm run deploy:apps
|
||||
|
||||
## Deployment
|
||||
|
||||
### Apps deployment
|
||||
|
||||
To deploy a new app version run:
|
||||
|
||||
$ aragon apm publish major --environment=NETWORK_TO_DEPLOY
|
||||
|
||||
### KreditsKit
|
||||
|
||||
deploy the KreditsKit as Kit to create new DAOs
|
||||
|
||||
$ truffle exec scripts/deploy-kit.js --network=NETWORK_TO_DEPLOY
|
||||
|
||||
### Creating a new DAO
|
||||
|
||||
make sure all apps and the KreditsKit are deployed, then create a new DAO:
|
||||
|
||||
$ truffle exec scripts/new-dao.js --network=NETWORK_TO_DEPLOY
|
||||
|
||||
## ACL / Permissions
|
||||
|
||||
## Upgradeable contracts
|
||||
|
||||
We use aragonOS for upgradeablity of the different contracts. Refer to the
|
||||
[aragonOS upgradeablity documentation](https://hack.aragon.org/docs/upgradeability-intro)
|
||||
for more details.
|
||||
|
||||
### Example
|
||||
|
||||
1. Setup (see #Bootstrap)
|
||||
1. Deploy each contract/apps (see `/apps/*`)
|
||||
2. Create a new DAO (see scripts/deploy-kit.js)
|
||||
2. Update
|
||||
1. Deploy a new Version of the contract/app (see `/apps/*`)
|
||||
2. Use the `aragon dao upgrade` command to "install" the new version for the DAO
|
||||
(`aragon dao upgrade <DAO address> <app name>`)
|
||||
|
||||
## Known Issues
|
||||
|
||||
When resetting ganache Metamask might have an invalid transaction nonce and
|
||||
transactions get rejected. Nonces in Ethereum must be incrementing and have no
|
||||
gap.
|
||||
|
||||
To solve this reset the metamask account (Account -> Settings -> Reset Account)
|
||||
153
README.mdown
153
README.mdown
@@ -1,153 +0,0 @@
|
||||
# Kredits
|
||||
|
||||
This repository contains all the contracts for Kredits as a [truffle framework](http://truffleframework.com/) project.
|
||||
|
||||
## Development
|
||||
|
||||
### Installation
|
||||
|
||||
$ npm install
|
||||
|
||||
### Requirements
|
||||
|
||||
All requirements are defined in `package.json`.
|
||||
|
||||
Those can be installed globally for convenience:
|
||||
* [truffle framework](http://truffleframework.com): `npm install -g truffle`
|
||||
* [ganache](http://truffleframework.com/ganache): `npm install -g ganache-cli`
|
||||
|
||||
We use following solidity contract libraries:
|
||||
* [Open Zeppelin](https://github.com/OpenZeppelin/zeppelin-solidity)
|
||||
|
||||
For local development it is recommended to use [ganache-cli](https://github.com/trufflesuite/ganache-cli) (or the [ganache GUI](http://truffleframework.com/ganache/) to run a local development chain.
|
||||
Using the ganache simulator no full Ethereum node is required.
|
||||
|
||||
We default to:
|
||||
|
||||
* port 7545 for development to not get in conflict with the default Ethereum RPC port.
|
||||
* network ID 100 to stay on the same network id
|
||||
* store ganache data in .ganache-db to presist the chain data across restarts
|
||||
* use a fixed Mnemonic code to get the same accounts across restarts
|
||||
|
||||
Have a look at `ganache-cli` for more configuration options.
|
||||
|
||||
Run your ganache simulator before using Kredits locally:
|
||||
|
||||
$ npm run ganache (which is: ganache-cli -p 7545 -i 100 --db=./.ganache-db -m kredits)
|
||||
|
||||
### Truffle console
|
||||
|
||||
Truffle comes with a simple REPL to interact with the Smart Contracts. Have a look at the [documentation here](http://truffleframework.com/docs/getting_started/console)
|
||||
|
||||
NOTE: There are promisses, have a look at the examples:
|
||||
|
||||
```javascript
|
||||
Token.deployed().then(function(token) {
|
||||
token.totalSupply.call().then(function(value) {
|
||||
console.log(value.toString());
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
Also please be aware of the differences between web3.js 0.2x.x and [1.x.x](https://web3js.readthedocs.io/en/1.0/) - [web3 repo](https://github.com/ethereum/web3.js/)
|
||||
|
||||
|
||||
## Contract Deployment
|
||||
|
||||
Truffle uses migration scripts to deploy contract to various networks. Have a look at the `migrations` folder for those.
|
||||
The Ethereum nodes for the different networks need to be configured in `truffle.js`.
|
||||
|
||||
Run the truffle migration scripts:
|
||||
|
||||
$ truffle deploy
|
||||
$ truffle deploy --network=<network config from truffle.js>
|
||||
|
||||
Truffle keeps track of already executed migration scripts. To reset the migration use the `--reset` option
|
||||
|
||||
$ truffle migrate --reset
|
||||
|
||||
Migration scripts can also be run from within `truffle console` or `truffle develop`
|
||||
|
||||
To initially bootstrap a local development chain in ganache you can use the bootstrap script:
|
||||
|
||||
$ npm run bootstrap (= `truffle migrate --reset && truffle exec scripts/seeds.js && npm run build-json`)
|
||||
|
||||
|
||||
## Helper scripts
|
||||
|
||||
`scripts/` contains some helper scripts to interact with the contracts from the CLI.
|
||||
At some point these should be moved into a real nice CLI.
|
||||
|
||||
To run these scripts use `truffle exec`. For example: `truffle exec scripts/add-proposal.js`
|
||||
|
||||
### cli.js
|
||||
|
||||
Call any function on any contract:
|
||||
|
||||
$ truffle exec scripts/cli.js <Contract Name> <Function> [<optional> <arguments>]
|
||||
|
||||
For example:
|
||||
$ truffle exec scripts/cli.js Operator proposalsCount
|
||||
|
||||
Please note that the contract name and the function are case sensitive.
|
||||
|
||||
### add-contributor.js
|
||||
Adds a new core contributor, creates a proposal for the new contributor and votes for that one.
|
||||
|
||||
$ truffle exec scripts/add-contributor.js <ethereum address> [<profile IPFS hash>]
|
||||
|
||||
### add-proposal.js
|
||||
Adds a new proposal for an existing contributor
|
||||
|
||||
$ truffle exec scripts/add-proposal.js <ethereum address> [<proposal IPFS hash>]
|
||||
|
||||
### send-funds.js
|
||||
Sends funds to an address. Helpful in development mode to for example fund a metamask account.
|
||||
|
||||
$ truffle exec scripts/send-funds.js <ethereum address>
|
||||
|
||||
### seeds.js
|
||||
Run seeds defined in `config/seeds.js`.
|
||||
|
||||
$ truffle exec scripts/seeds.js
|
||||
or
|
||||
$ npm run seeds
|
||||
|
||||
|
||||
## Upgradeable contracts
|
||||
|
||||
Some of the contracts use upgradability ideas from [zeppelinos](https://github.com/zeppelinos/labs) (see `contracts/upgradable`).
|
||||
|
||||
The basic idea is to have a Registry contract that knows about the current implementations and a Proxy contract that uses `delegatecall` to call the current implementation.
|
||||
That means the Proxy contract holds the storage and the address of that one does not change but the actuall implemenation is managed through the Registry.
|
||||
|
||||
To deploy a new version a new contract is deployed then the version is registered (`addVersion()`) in the Registry and on the Proxy contract is "upgraded" (`upgrade()`) to the new version.
|
||||
|
||||
The Registry knows about all the different contracts and implementations. Versions are stored as uint and automatically incremented for every added implementation.
|
||||
|
||||
|
||||
### Example:
|
||||
|
||||
Deployment is best done using the [truffle deployer]()
|
||||
|
||||
1. Setup
|
||||
1. deploy the Registry
|
||||
2. deploy the contract
|
||||
3. register the contract at the Registry:
|
||||
`registry.addVersion('Token', Token.address)`
|
||||
4. create the Proxy:
|
||||
`registry.createProxy('Token', 1)`
|
||||
2. Update
|
||||
1. deploy a new Version of the contract
|
||||
2. register the new version at the Registry:
|
||||
`registry.addVersion('Token', NewToken.address)`
|
||||
3. set the new implementation address on the Proxy contract:
|
||||
`registry.upgrade('Token', 2)`
|
||||
|
||||
|
||||
## Known Issues
|
||||
|
||||
When resetting ganache Metamask might have an invalid transaction nonce and transactions get rejected.
|
||||
Nonces in Ethereum must be incrementing and have no gap.
|
||||
|
||||
To solve this reset the metamask account (Account -> Settings -> Reset Account)
|
||||
12
apps/.eslintrc.js
Normal file
12
apps/.eslintrc.js
Normal file
@@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
'globals': {
|
||||
contract: true,
|
||||
describe: true,
|
||||
it: true,
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['error', {
|
||||
'argsIgnorePattern': '^_',
|
||||
}],
|
||||
}
|
||||
}
|
||||
4
apps/contribution/.gitignore
vendored
Normal file
4
apps/contribution/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
node_modules
|
||||
build
|
||||
.cache
|
||||
dist
|
||||
14
apps/contribution/.ipfsignore
Normal file
14
apps/contribution/.ipfsignore
Normal file
@@ -0,0 +1,14 @@
|
||||
# Git files
|
||||
.gitignore
|
||||
|
||||
# Build files
|
||||
.cache
|
||||
node_modules
|
||||
build
|
||||
|
||||
# Lock files
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
# Others
|
||||
test
|
||||
1
apps/contribution/README.md
Normal file
1
apps/contribution/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# Kredits Contribution
|
||||
38
apps/contribution/arapp.json
Normal file
38
apps/contribution/arapp.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"roles": [
|
||||
{
|
||||
"name": "Add contributions",
|
||||
"id": "ADD_CONTRIBUTION_ROLE",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"name": "Manage token contract",
|
||||
"id": "MANAGE_TOKEN_CONTRACT_ROLE",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"name": "Veto contributions",
|
||||
"id": "VETO_CONTRIBUTION_ROLE",
|
||||
"params": []
|
||||
}
|
||||
],
|
||||
"environments": {
|
||||
"default": {
|
||||
"network": "development",
|
||||
"appName": "kredits-contribution.open.aragonpm.eth"
|
||||
},
|
||||
"rinkeby": {
|
||||
"registry": "0x98df287b6c145399aaa709692c8d308357bc085d",
|
||||
"appName": "kredits-contribution.open.aragonpm.eth",
|
||||
"wsRPC": "wss://rinkeby.eth.aragon.network/ws",
|
||||
"network": "rinkeby"
|
||||
},
|
||||
"production": {
|
||||
"registry": "0x314159265dd8dbb310642f98f50c066173c1259b",
|
||||
"appName": "contribution.open.aragonpm.eth",
|
||||
"wsRPC": "wss://mainnet.eth.aragon.network/ws",
|
||||
"network": "mainnet"
|
||||
}
|
||||
},
|
||||
"path": "contracts/Contribution.sol"
|
||||
}
|
||||
912
apps/contribution/artifact.json
Normal file
912
apps/contribution/artifact.json
Normal file
@@ -0,0 +1,912 @@
|
||||
{
|
||||
"roles": [
|
||||
{
|
||||
"name": "Add contributions",
|
||||
"id": "ADD_CONTRIBUTION_ROLE",
|
||||
"params": [],
|
||||
"bytes": "0x493d28cd0d82bcb20db66e4f6390a00122ef772717e282b436ba3240af18bfb1"
|
||||
},
|
||||
{
|
||||
"name": "Manage token contract",
|
||||
"id": "MANAGE_TOKEN_CONTRACT_ROLE",
|
||||
"params": [],
|
||||
"bytes": "0xdd275187bc43df45ce7b34f6716e572716c69ad44e5e496175008950f032854b"
|
||||
},
|
||||
{
|
||||
"name": "Veto contributions",
|
||||
"id": "VETO_CONTRIBUTION_ROLE",
|
||||
"params": [],
|
||||
"bytes": "0x495a36de1ed34d5c1b9f8704e7d8bc8badb027221b09c79691d430bc54c4c88f"
|
||||
}
|
||||
],
|
||||
"environments": {
|
||||
"default": {
|
||||
"network": "development",
|
||||
"appName": "kredits-contribution.open.aragonpm.eth"
|
||||
}
|
||||
},
|
||||
"path": "contracts/Contribution.sol",
|
||||
"appName": "kredits-contribution.open.aragonpm.eth",
|
||||
"appId": "0x09f5274cba299b46c5be722ef672d10eef7a2ef980b612aef529d74fb9da7643",
|
||||
"abi": [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "hasInitialized",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "ADD_CONTRIBUTION_ROLE",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_script",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "getEVMScriptExecutor",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getRecoveryVault",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "contributionsCount",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowRecoverability",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "appId",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getInitializationBlock",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "KERNEL_APP_ADDR_NAMESPACE",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferToVault",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_sender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_role",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "_params",
|
||||
"type": "uint256[]"
|
||||
}
|
||||
],
|
||||
"name": "canPerform",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getEVMScriptRegistry",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "contributionOwner",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "contributions",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "contributorId",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "amount",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "claimed",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "hashDigest",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "hashFunction",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "hashSize",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "tokenMetadataURL",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "confirmedAtBlock",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "vetoed",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "exists",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "ownedContributions",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "kernel",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "blocksToWait",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "isPetrified",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "appIds",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "VETO_CONTRIBUTION_ROLE",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "id",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "contributorId",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "amount",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "ContributionAdded",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "id",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "contributorId",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "amount",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "ContributionClaimed",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "id",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "vetoedByAccount",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "ContributionVetoed",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "executor",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "script",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "input",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "returnData",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "ScriptResult",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "vault",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "RecoverToVault",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_appIds",
|
||||
"type": "bytes32[4]"
|
||||
}
|
||||
],
|
||||
"name": "initialize",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getTokenContract",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getContributorContract",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "contributorAccount",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "getContributorIdByAddress",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "contributorId",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "getContributorAddressById",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "name",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "symbol",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "contributionId",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "ownerOf",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "index",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "tokenOfOwnerByIndex",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "contributionId",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "tokenMetadata",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "confirmedOnly",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"name": "totalKreditsEarned",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "amount",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "contributorId",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "confirmedOnly",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"name": "totalKreditsEarnedByContributor",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "amount",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "contributionId",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "getContribution",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "contributorId",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "amount",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "claimed",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "hashDigest",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "hashFunction",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "hashSize",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "confirmedAtBlock",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "exists",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "vetoed",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "amount",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "contributorId",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "hashDigest",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "hashFunction",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "hashSize",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"name": "add",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "contributionId",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "veto",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "contributionId",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "claim",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "contributionId",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "exists",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
"deployment": {
|
||||
"contractName": "Contribution",
|
||||
"compiledAt": "2019-06-13T12:39:07.659Z",
|
||||
"compiler": {
|
||||
"name": "solc",
|
||||
"version": "0.4.24+commit.e67f0147.Emscripten.clang",
|
||||
"optimizer": {
|
||||
"enabled": false
|
||||
}
|
||||
},
|
||||
"flattenedCode": "./code.sol",
|
||||
"transactionHash": "0x073057bb616243e415823fa9a8c8cc096b573fbd0bbf11c2f59bb75a84291689"
|
||||
},
|
||||
"functions": [
|
||||
{
|
||||
"sig": "mintFor(address,uint256,uint32)",
|
||||
"roles": [],
|
||||
"notice": null
|
||||
},
|
||||
{
|
||||
"sig": "initialize(bytes32[4])",
|
||||
"roles": [],
|
||||
"notice": null
|
||||
},
|
||||
{
|
||||
"sig": "add(uint32,uint32,bytes32,uint8,uint8)",
|
||||
"roles": [
|
||||
"ADD_CONTRIBUTION_ROLE"
|
||||
],
|
||||
"notice": null
|
||||
},
|
||||
{
|
||||
"sig": "veto(uint32)",
|
||||
"roles": [
|
||||
"VETO_CONTRIBUTION_ROLE"
|
||||
],
|
||||
"notice": null
|
||||
},
|
||||
{
|
||||
"sig": "claim(uint32)",
|
||||
"roles": [],
|
||||
"notice": null
|
||||
}
|
||||
]
|
||||
}
|
||||
1252
apps/contribution/code.sol
Normal file
1252
apps/contribution/code.sol
Normal file
File diff suppressed because it is too large
Load Diff
211
apps/contribution/contracts/Contribution.sol
Normal file
211
apps/contribution/contracts/Contribution.sol
Normal file
@@ -0,0 +1,211 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "@aragon/os/contracts/apps/AragonApp.sol";
|
||||
import "@aragon/os/contracts/kernel/IKernel.sol";
|
||||
|
||||
interface IToken {
|
||||
function mintFor(address contributorAccount, uint256 amount, uint32 contributionId) public;
|
||||
}
|
||||
|
||||
interface ContributorInterface {
|
||||
function getContributorAddressById(uint32 contributorId) public view returns (address);
|
||||
function getContributorIdByAddress(address contributorAccount) public view returns (uint32);
|
||||
// TODO Maybe use for validation
|
||||
// function exists(uint32 contributorId) public view returns (bool);
|
||||
}
|
||||
|
||||
contract Contribution is AragonApp {
|
||||
bytes32 public constant ADD_CONTRIBUTION_ROLE = keccak256("ADD_CONTRIBUTION_ROLE");
|
||||
bytes32 public constant VETO_CONTRIBUTION_ROLE = keccak256("VETO_CONTRIBUTION_ROLE");
|
||||
|
||||
bytes32 public constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb;
|
||||
|
||||
// ensure alphabetic order
|
||||
enum Apps { Contribution, Contributor, Proposal, Token }
|
||||
bytes32[4] public appIds;
|
||||
|
||||
struct ContributionData {
|
||||
uint32 contributorId;
|
||||
uint32 amount;
|
||||
bool claimed;
|
||||
bytes32 hashDigest;
|
||||
uint8 hashFunction;
|
||||
uint8 hashSize;
|
||||
string tokenMetadataURL;
|
||||
uint256 confirmedAtBlock;
|
||||
bool vetoed;
|
||||
bool exists;
|
||||
}
|
||||
|
||||
string internal name_;
|
||||
string internal symbol_;
|
||||
|
||||
// map contribution ID to contributor
|
||||
mapping(uint32 => uint32) public contributionOwner;
|
||||
// map contributor to contribution IDs
|
||||
mapping(uint32 => uint32[]) public ownedContributions;
|
||||
|
||||
mapping(uint32 => ContributionData) public contributions;
|
||||
uint32 public contributionsCount;
|
||||
|
||||
uint32 public blocksToWait;
|
||||
|
||||
event ContributionAdded(uint32 id, uint32 indexed contributorId, uint32 amount);
|
||||
event ContributionClaimed(uint32 id, uint32 indexed contributorId, uint32 amount);
|
||||
event ContributionVetoed(uint32 id, address vetoedByAccount);
|
||||
|
||||
function initialize(bytes32[4] _appIds) public onlyInit {
|
||||
appIds = _appIds;
|
||||
blocksToWait = 40320; // 7 days; 15 seconds block time
|
||||
initialized();
|
||||
}
|
||||
|
||||
// TODO refactor into a single function
|
||||
function getTokenContract() public view returns (address) {
|
||||
IKernel k = IKernel(kernel());
|
||||
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Token)]);
|
||||
}
|
||||
function getContributorContract() public view returns (address) {
|
||||
IKernel k = IKernel(kernel());
|
||||
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contributor)]);
|
||||
}
|
||||
|
||||
function getContributorIdByAddress(address contributorAccount) public view returns (uint32) {
|
||||
address contributor = getContributorContract();
|
||||
return ContributorInterface(contributor).getContributorIdByAddress(contributorAccount);
|
||||
}
|
||||
|
||||
function getContributorAddressById(uint32 contributorId) public view returns (address) {
|
||||
address contributor = getContributorContract();
|
||||
return ContributorInterface(contributor).getContributorAddressById(contributorId);
|
||||
}
|
||||
|
||||
//
|
||||
// Token standard functions (ERC 721)
|
||||
//
|
||||
|
||||
function name() external view returns (string) {
|
||||
return name_;
|
||||
}
|
||||
|
||||
function symbol() external view returns (string) {
|
||||
return symbol_;
|
||||
}
|
||||
|
||||
// Balance is amount of ERC271 tokens, not amount of kredits
|
||||
function balanceOf(address owner) public view returns (uint256) {
|
||||
require(owner != address(0));
|
||||
uint32 contributorId = getContributorIdByAddress(owner);
|
||||
return ownedContributions[contributorId].length;
|
||||
}
|
||||
|
||||
function ownerOf(uint32 contributionId) public view returns (address) {
|
||||
require(exists(contributionId));
|
||||
uint32 contributorId = contributions[contributionId].contributorId;
|
||||
return getContributorAddressById(contributorId);
|
||||
}
|
||||
|
||||
function tokenOfOwnerByIndex(address owner, uint32 index) public view returns (uint32) {
|
||||
uint32 contributorId = getContributorIdByAddress(owner);
|
||||
return ownedContributions[contributorId][index];
|
||||
}
|
||||
|
||||
function tokenMetadata(uint32 contributionId) public view returns (string) {
|
||||
return contributions[contributionId].tokenMetadataURL;
|
||||
}
|
||||
|
||||
//
|
||||
// Custom functions
|
||||
//
|
||||
|
||||
function totalKreditsEarned(bool confirmedOnly) public view returns (uint32 amount) {
|
||||
for (uint32 i = 1; i <= contributionsCount; i++) {
|
||||
ContributionData memory c = contributions[i];
|
||||
if (!c.vetoed && (block.number >= c.confirmedAtBlock || !confirmedOnly)) {
|
||||
amount += c.amount; // should use safemath
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function totalKreditsEarnedByContributor(uint32 contributorId, bool confirmedOnly) public view returns (uint32 amount) {
|
||||
uint256 tokenCount = ownedContributions[contributorId].length;
|
||||
for (uint256 i = 0; i < tokenCount; i++) {
|
||||
uint32 cId = ownedContributions[contributorId][i];
|
||||
ContributionData memory c = contributions[cId];
|
||||
if (!c.vetoed && (block.number >= c.confirmedAtBlock || !confirmedOnly)) {
|
||||
amount += c.amount; // should use safemath
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getContribution(uint32 contributionId) public view returns (uint32 id, uint32 contributorId, uint32 amount, bool claimed, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint256 confirmedAtBlock, bool exists, bool vetoed) {
|
||||
id = contributionId;
|
||||
ContributionData storage c = contributions[id];
|
||||
return (
|
||||
id,
|
||||
c.contributorId,
|
||||
c.amount,
|
||||
c.claimed,
|
||||
c.hashDigest,
|
||||
c.hashFunction,
|
||||
c.hashSize,
|
||||
c.confirmedAtBlock,
|
||||
c.exists,
|
||||
c.vetoed
|
||||
);
|
||||
}
|
||||
|
||||
function add(uint32 amount, uint32 contributorId, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(ADD_CONTRIBUTION_ROLE) {
|
||||
//require(canPerform(msg.sender, ADD_CONTRIBUTION_ROLE, new uint32[](0)), 'nope');
|
||||
uint32 contributionId = contributionsCount + 1;
|
||||
ContributionData storage c = contributions[contributionId];
|
||||
c.exists = true;
|
||||
c.amount = amount;
|
||||
c.claimed = false;
|
||||
c.contributorId = contributorId;
|
||||
c.hashDigest = hashDigest;
|
||||
c.hashFunction = hashFunction;
|
||||
c.hashSize = hashSize;
|
||||
if (contributionId < 10) {
|
||||
c.confirmedAtBlock = block.number;
|
||||
} else {
|
||||
c.confirmedAtBlock = block.number + blocksToWait;
|
||||
}
|
||||
|
||||
contributionsCount++;
|
||||
|
||||
contributionOwner[contributionId] = contributorId;
|
||||
ownedContributions[contributorId].push(contributionId);
|
||||
|
||||
emit ContributionAdded(contributionId, contributorId, amount);
|
||||
}
|
||||
|
||||
function veto(uint32 contributionId) public isInitialized auth(VETO_CONTRIBUTION_ROLE) {
|
||||
ContributionData storage c = contributions[contributionId];
|
||||
require(c.exists, 'NOT_FOUND');
|
||||
require(!c.claimed, 'ALREADY_CLAIMED');
|
||||
require(block.number < c.confirmedAtBlock, 'VETO_PERIOD_ENDED');
|
||||
c.vetoed = true;
|
||||
|
||||
emit ContributionVetoed(contributionId, msg.sender);
|
||||
}
|
||||
|
||||
function claim(uint32 contributionId) public isInitialized {
|
||||
ContributionData storage c = contributions[contributionId];
|
||||
require(c.exists, 'NOT_FOUND');
|
||||
require(!c.claimed, 'ALREADY_CLAIMED');
|
||||
require(!c.vetoed, 'VETOED');
|
||||
require(block.number >= c.confirmedAtBlock, 'NOT_CLAIMABLE');
|
||||
|
||||
c.claimed = true;
|
||||
address token = getTokenContract();
|
||||
address contributorAccount = getContributorAddressById(c.contributorId);
|
||||
uint256 amount = uint256(c.amount);
|
||||
IToken(token).mintFor(contributorAccount, amount, contributionId);
|
||||
emit ContributionClaimed(contributionId, c.contributorId, c.amount);
|
||||
}
|
||||
|
||||
function exists(uint32 contributionId) view public returns (bool) {
|
||||
return contributions[contributionId].exists;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.17;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
contract Migrations {
|
||||
address public owner;
|
||||
@@ -8,7 +8,7 @@ contract Migrations {
|
||||
if (msg.sender == owner) _;
|
||||
}
|
||||
|
||||
function Migrations() public {
|
||||
constructor() public {
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
4
apps/contribution/manifest.json
Normal file
4
apps/contribution/manifest.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "Contribution",
|
||||
"description": "Kredits contribution app"
|
||||
}
|
||||
5
apps/contribution/migrations/1_initial_migration.js
Normal file
5
apps/contribution/migrations/1_initial_migration.js
Normal file
@@ -0,0 +1,5 @@
|
||||
var Migrations = artifacts.require('./Migrations.sol')
|
||||
|
||||
module.exports = function (deployer) {
|
||||
deployer.deploy(Migrations)
|
||||
}
|
||||
5
apps/contribution/migrations/2_deploy_contracts.js
Normal file
5
apps/contribution/migrations/2_deploy_contracts.js
Normal file
@@ -0,0 +1,5 @@
|
||||
var Contribution = artifacts.require('Contribution.sol')
|
||||
|
||||
module.exports = function (deployer) {
|
||||
deployer.deploy(Contribution)
|
||||
}
|
||||
28459
apps/contribution/package-lock.json
generated
Normal file
28459
apps/contribution/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
35
apps/contribution/package.json
Normal file
35
apps/contribution/package.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "kredits-contribution",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"@aragon/os": "^4.2.0",
|
||||
"@aragon/cli": "^5.9.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aragon/test-helpers": "^1.1.0",
|
||||
"eth-gas-reporter": "^0.2.0",
|
||||
"ganache-cli": "^6.4.3",
|
||||
"solidity-coverage": "^0.5.11"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "npm run start:aragon:ipfs",
|
||||
"start:aragon:ipfs": "aragon run",
|
||||
"start:aragon:http": "aragon run --http localhost:8001 --http-served-from ./dist",
|
||||
"start:app": "",
|
||||
"compile": "aragon contracts compile",
|
||||
"sync-assets": "",
|
||||
"build:app": "",
|
||||
"build:script": "",
|
||||
"build": "",
|
||||
"publish:patch": "aragon apm publish patch",
|
||||
"publish:minor": "aragon apm publish minor",
|
||||
"publish:major": "aragon apm publish major",
|
||||
"versions": "aragon apm versions",
|
||||
"test": "TRUFFLE_TEST=true PORT=7545 npm run ganache-cli:test",
|
||||
"test:gas": "GAS_REPORTER=true npm test",
|
||||
"coverage": "SOLIDITY_COVERAGE=true npm run ganache-cli:test",
|
||||
"ganache-cli:test": "./node_modules/@aragon/test-helpers/ganache-cli.sh"
|
||||
},
|
||||
"keywords": []
|
||||
}
|
||||
5
apps/contribution/test/app.js
Normal file
5
apps/contribution/test/app.js
Normal file
@@ -0,0 +1,5 @@
|
||||
// const Contribution = artifacts.require('Contribution.sol');
|
||||
|
||||
contract('Contribution', (_accounts) => {
|
||||
it('should be tested');
|
||||
});
|
||||
1
apps/contribution/truffle.js
Normal file
1
apps/contribution/truffle.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require("../../truffle.js");
|
||||
8145
apps/contribution/yarn.lock
Normal file
8145
apps/contribution/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
4
apps/contributor/.gitignore
vendored
Normal file
4
apps/contributor/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
node_modules
|
||||
build
|
||||
.cache
|
||||
dist
|
||||
14
apps/contributor/.ipfsignore
Normal file
14
apps/contributor/.ipfsignore
Normal file
@@ -0,0 +1,14 @@
|
||||
# Git files
|
||||
.gitignore
|
||||
|
||||
# Build files
|
||||
.cache
|
||||
node_modules
|
||||
build
|
||||
|
||||
# Lock files
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
# Others
|
||||
test
|
||||
1
apps/contributor/README.md
Normal file
1
apps/contributor/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# Kredits Contributor
|
||||
28
apps/contributor/arapp.json
Normal file
28
apps/contributor/arapp.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"roles": [
|
||||
{
|
||||
"name": "Manage contributors",
|
||||
"id": "MANAGE_CONTRIBUTORS_ROLE",
|
||||
"params": []
|
||||
}
|
||||
],
|
||||
"environments": {
|
||||
"default": {
|
||||
"network": "development",
|
||||
"appName": "kredits-contributor.open.aragonpm.eth"
|
||||
},
|
||||
"rinkeby": {
|
||||
"registry": "0x98df287b6c145399aaa709692c8d308357bc085d",
|
||||
"appName": "kredits-contributor.open.aragonpm.eth",
|
||||
"wsRPC": "wss://rinkeby.eth.aragon.network/ws",
|
||||
"network": "rinkeby"
|
||||
},
|
||||
"production": {
|
||||
"registry": "0x314159265dd8dbb310642f98f50c066173c1259b",
|
||||
"appName": "contributor.open.aragonpm.eth",
|
||||
"wsRPC": "wss://mainnet.eth.aragon.network/ws",
|
||||
"network": "mainnet"
|
||||
}
|
||||
},
|
||||
"path": "contracts/Contributor.sol"
|
||||
}
|
||||
159
apps/contributor/contracts/Contributor.sol
Normal file
159
apps/contributor/contracts/Contributor.sol
Normal file
@@ -0,0 +1,159 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "@aragon/os/contracts/apps/AragonApp.sol";
|
||||
import "@aragon/os/contracts/kernel/IKernel.sol";
|
||||
|
||||
interface ITokenBalance {
|
||||
function balanceOf(address contributorAccount) public view returns (uint256);
|
||||
}
|
||||
interface IContributionBalance {
|
||||
function totalKreditsEarnedByContributor(uint32 contributorId, bool confirmedOnly) public view returns (uint32 amount);
|
||||
function balanceOf(address owner) public view returns (uint256);
|
||||
}
|
||||
|
||||
contract Contributor is AragonApp {
|
||||
bytes32 public constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb;
|
||||
bytes32 public constant MANAGE_CONTRIBUTORS_ROLE = keccak256("MANAGE_CONTRIBUTORS_ROLE");
|
||||
|
||||
struct Contributor {
|
||||
address account;
|
||||
bytes32 hashDigest;
|
||||
uint8 hashFunction;
|
||||
uint8 hashSize;
|
||||
bool exists;
|
||||
}
|
||||
|
||||
mapping (address => uint32) public contributorIds;
|
||||
mapping (uint32 => Contributor) public contributors;
|
||||
uint32 public contributorsCount;
|
||||
|
||||
// ensure alphabetic order
|
||||
enum Apps { Contribution, Contributor, Proposal, Token }
|
||||
bytes32[4] public appIds;
|
||||
|
||||
event ContributorProfileUpdated(uint32 id, bytes32 oldHashDigest, bytes32 newHashDigest); // what should be logged
|
||||
event ContributorAccountUpdated(uint32 id, address oldAccount, address newAccount);
|
||||
event ContributorAdded(uint32 id, address account);
|
||||
|
||||
function initialize(address root,bytes32[4] _appIds) public onlyInit {
|
||||
appIds = _appIds;
|
||||
|
||||
initialized();
|
||||
}
|
||||
|
||||
function getTokenContract() public view returns (address) {
|
||||
IKernel k = IKernel(kernel());
|
||||
|
||||
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Token)]);
|
||||
}
|
||||
|
||||
function getContributionContract() public view returns (address) {
|
||||
IKernel k = IKernel(kernel());
|
||||
|
||||
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contribution)]);
|
||||
}
|
||||
|
||||
function coreContributorsCount() view public returns (uint32) {
|
||||
uint32 count = 0;
|
||||
for (uint32 i = 1; i <= contributorsCount; i++) {
|
||||
if (isCoreTeam(i)) {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
function updateContributorAccount(uint32 id, address oldAccount, address newAccount) public auth(MANAGE_CONTRIBUTORS_ROLE) {
|
||||
contributorIds[oldAccount] = 0;
|
||||
contributorIds[newAccount] = id;
|
||||
contributors[id].account = newAccount;
|
||||
ContributorAccountUpdated(id, oldAccount, newAccount);
|
||||
}
|
||||
|
||||
function updateContributorProfileHash(uint32 id, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(MANAGE_CONTRIBUTORS_ROLE) {
|
||||
Contributor storage c = contributors[id];
|
||||
bytes32 oldHashDigest = c.hashDigest;
|
||||
c.hashDigest = hashDigest;
|
||||
c.hashFunction = hashFunction;
|
||||
c.hashSize = hashSize;
|
||||
|
||||
ContributorProfileUpdated(id, oldHashDigest, c.hashDigest);
|
||||
}
|
||||
|
||||
function addContributor(address account, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(MANAGE_CONTRIBUTORS_ROLE) {
|
||||
require(!addressExists(account));
|
||||
uint32 _id = contributorsCount + 1;
|
||||
assert(!contributors[_id].exists); // this can not be acually
|
||||
Contributor storage c = contributors[_id];
|
||||
c.exists = true;
|
||||
c.hashDigest = hashDigest;
|
||||
c.hashFunction = hashFunction;
|
||||
c.hashSize = hashSize;
|
||||
c.account = account;
|
||||
contributorIds[account] = _id;
|
||||
|
||||
contributorsCount += 1;
|
||||
emit ContributorAdded(_id, account);
|
||||
}
|
||||
|
||||
function isCoreTeam(uint32 id) view public returns (bool) {
|
||||
// TODO: for simplicity we simply define the first contributors as core
|
||||
// later this needs to be changed to something more dynamic
|
||||
return id < 7;
|
||||
}
|
||||
|
||||
function exists(uint32 id) view public returns (bool) {
|
||||
return contributors[id].exists;
|
||||
}
|
||||
|
||||
function addressIsCore(address account) view public returns (bool) {
|
||||
uint32 id = getContributorIdByAddress(account);
|
||||
return isCoreTeam(id);
|
||||
}
|
||||
|
||||
function addressExists(address account) view public returns (bool) {
|
||||
return getContributorByAddress(account).exists;
|
||||
}
|
||||
|
||||
function getContributorIdByAddress(address account) view public returns (uint32) {
|
||||
return contributorIds[account];
|
||||
}
|
||||
|
||||
function getContributorAddressById(uint32 id) view public returns (address) {
|
||||
return contributors[id].account;
|
||||
}
|
||||
|
||||
function getContributorByAddress(address account) internal view returns (Contributor) {
|
||||
uint32 id = contributorIds[account];
|
||||
return contributors[id];
|
||||
}
|
||||
|
||||
function getContributorById(uint32 _id) public view returns (uint32 id, address account, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, bool isCore, uint256 balance, uint32 totalKreditsEarned, uint256 contributionsCount, bool exists ) {
|
||||
id = _id;
|
||||
Contributor storage c = contributors[_id];
|
||||
account = c.account;
|
||||
hashDigest = c.hashDigest;
|
||||
hashFunction = c.hashFunction;
|
||||
hashSize = c.hashSize;
|
||||
isCore = isCoreTeam(id);
|
||||
address token = getTokenContract();
|
||||
balance = ITokenBalance(token).balanceOf(c.account);
|
||||
address contribution = getContributionContract();
|
||||
totalKreditsEarned = IContributionBalance(contribution).totalKreditsEarnedByContributor(_id, true);
|
||||
contributionsCount = IContributionBalance(contribution).balanceOf(c.account);
|
||||
exists = c.exists;
|
||||
}
|
||||
|
||||
function canPerform(address _who, address _where, bytes32 _what, uint256[] memory _how) public returns (bool) {
|
||||
address sender = _who;
|
||||
if (sender == address(-1)) {
|
||||
sender = tx.origin;
|
||||
}
|
||||
// _what == keccak256('VOTE_PROPOSAL_ROLE')
|
||||
if (_what == 0xd61216798314d2fc33e42ff2021d66707b1e38517d3f7166798a9d3a196a9c96) {
|
||||
return contributorIds[sender] != uint256(0);
|
||||
}
|
||||
|
||||
return addressIsCore(sender);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.17;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
contract Migrations {
|
||||
address public owner;
|
||||
@@ -8,7 +8,7 @@ contract Migrations {
|
||||
if (msg.sender == owner) _;
|
||||
}
|
||||
|
||||
function Migrations() public {
|
||||
constructor() public {
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
4
apps/contributor/manifest.json
Normal file
4
apps/contributor/manifest.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "Contributor",
|
||||
"description": "Kredits Contributor app"
|
||||
}
|
||||
5
apps/contributor/migrations/1_initial_migration.js
Normal file
5
apps/contributor/migrations/1_initial_migration.js
Normal file
@@ -0,0 +1,5 @@
|
||||
var Migrations = artifacts.require('./Migrations.sol')
|
||||
|
||||
module.exports = function (deployer) {
|
||||
deployer.deploy(Migrations)
|
||||
}
|
||||
5
apps/contributor/migrations/2_deploy_contracts.js
Normal file
5
apps/contributor/migrations/2_deploy_contracts.js
Normal file
@@ -0,0 +1,5 @@
|
||||
var Contributor = artifacts.require('Contributor.sol')
|
||||
|
||||
module.exports = function (deployer) {
|
||||
deployer.deploy(Contributor)
|
||||
}
|
||||
28459
apps/contributor/package-lock.json
generated
Normal file
28459
apps/contributor/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
35
apps/contributor/package.json
Normal file
35
apps/contributor/package.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "kredits-contributor",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"@aragon/os": "^4.2.0",
|
||||
"@aragon/cli": "^5.9.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aragon/test-helpers": "^1.1.0",
|
||||
"eth-gas-reporter": "^0.2.0",
|
||||
"ganache-cli": "^6.4.3",
|
||||
"solidity-coverage": "^0.5.11"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "npm run start:aragon:ipfs",
|
||||
"start:aragon:ipfs": "aragon run",
|
||||
"start:aragon:http": "aragon run --http localhost:8001 --http-served-from ./dist",
|
||||
"start:app": "",
|
||||
"compile": "aragon contracts compile",
|
||||
"sync-assets": "",
|
||||
"build:app": "",
|
||||
"build:script": "",
|
||||
"build": "",
|
||||
"publish:patch": "aragon apm publish patch",
|
||||
"publish:minor": "aragon apm publish minor",
|
||||
"publish:major": "aragon apm publish major",
|
||||
"versions": "aragon apm versions",
|
||||
"test": "TRUFFLE_TEST=true PORT=7545 npm run ganache-cli:test",
|
||||
"test:gas": "GAS_REPORTER=true npm test",
|
||||
"coverage": "SOLIDITY_COVERAGE=true npm run ganache-cli:test",
|
||||
"ganache-cli:test": "./node_modules/@aragon/test-helpers/ganache-cli.sh"
|
||||
},
|
||||
"keywords": []
|
||||
}
|
||||
5
apps/contributor/test/app.js
Normal file
5
apps/contributor/test/app.js
Normal file
@@ -0,0 +1,5 @@
|
||||
// const Contributor = artifacts.require('Contributor.sol');
|
||||
|
||||
contract('Contributor', (_accounts) => {
|
||||
it('should be tested');
|
||||
});
|
||||
1
apps/contributor/truffle.js
Normal file
1
apps/contributor/truffle.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require("../../truffle.js");
|
||||
8145
apps/contributor/yarn.lock
Normal file
8145
apps/contributor/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
1
apps/proposal/README.md
Normal file
1
apps/proposal/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# Kredits Proposal
|
||||
33
apps/proposal/arapp.json
Normal file
33
apps/proposal/arapp.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"roles": [
|
||||
{
|
||||
"name": "Add proposal",
|
||||
"id": "ADD_PROPOSAL_ROLE",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"name": "Vote proposals",
|
||||
"id": "VOTE_PROPOSAL_ROLE",
|
||||
"params": []
|
||||
}
|
||||
],
|
||||
"environments": {
|
||||
"default": {
|
||||
"network": "development",
|
||||
"appName": "kredits-proposal.open.aragonpm.eth"
|
||||
},
|
||||
"rinkeby": {
|
||||
"registry": "0x98df287b6c145399aaa709692c8d308357bc085d",
|
||||
"appName": "kredits-proposal.open.aragonpm.eth",
|
||||
"wsRPC": "wss://rinkeby.eth.aragon.network/ws",
|
||||
"network": "rinkeby"
|
||||
},
|
||||
"production": {
|
||||
"registry": "0x314159265dd8dbb310642f98f50c066173c1259b",
|
||||
"appName": "proposal.open.aragonpm.eth",
|
||||
"wsRPC": "wss://mainnet.eth.aragon.network/ws",
|
||||
"network": "mainnet"
|
||||
}
|
||||
},
|
||||
"path": "contracts/Proposal.sol"
|
||||
}
|
||||
133
apps/proposal/contracts/Proposal.sol
Normal file
133
apps/proposal/contracts/Proposal.sol
Normal file
@@ -0,0 +1,133 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "@aragon/os/contracts/apps/AragonApp.sol";
|
||||
import "@aragon/os/contracts/kernel/IKernel.sol";
|
||||
|
||||
interface IContributor {
|
||||
function getContributorAddressById(uint32 contributorId) public view returns (address);
|
||||
function getContributorIdByAddress(address contributorAccount) public view returns (uint32);
|
||||
function exists(uint32 contributorId) public view returns (bool);
|
||||
}
|
||||
|
||||
interface IContribution {
|
||||
function add(uint32 amount, uint32 contributorId, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public;
|
||||
}
|
||||
|
||||
contract Proposal is AragonApp {
|
||||
|
||||
bytes32 public constant ADD_PROPOSAL_ROLE = keccak256("ADD_PROPOSAL_ROLE");
|
||||
bytes32 public constant VOTE_PROPOSAL_ROLE = keccak256("VOTE_PROPOSAL_ROLE");
|
||||
|
||||
bytes32 public constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb;
|
||||
// ensure alphabetic order
|
||||
enum Apps { Contribution, Contributor, Proposal, Token }
|
||||
bytes32[4] public appIds;
|
||||
|
||||
struct Proposal {
|
||||
address creatorAccount;
|
||||
uint32 contributorId;
|
||||
uint16 votesCount;
|
||||
uint16 votesNeeded;
|
||||
uint32 amount;
|
||||
bool executed;
|
||||
bytes32 hashDigest;
|
||||
uint8 hashFunction;
|
||||
uint8 hashSize;
|
||||
uint32[] voterIds;
|
||||
mapping (uint32 => bool) votes;
|
||||
bool exists;
|
||||
}
|
||||
|
||||
mapping(uint32 => Proposal) public proposals;
|
||||
uint32 public proposalsCount;
|
||||
|
||||
event ProposalCreated(uint32 id, address creatorAccount, uint32 contributorId, uint32 amount);
|
||||
|
||||
event ProposalVoted(uint32 id, uint32 voterId, uint16 totalVotes);
|
||||
event ProposalExecuted(uint32 id, uint32 contributorId, uint32 amount);
|
||||
|
||||
function initialize(bytes32[4] _appIds) public onlyInit {
|
||||
appIds = _appIds;
|
||||
initialized();
|
||||
}
|
||||
|
||||
function getContributorContract() public view returns (address) {
|
||||
return IKernel(kernel()).getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contributor)]);
|
||||
}
|
||||
|
||||
function getContributionContract() public view returns (address) {
|
||||
return IKernel(kernel()).getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contribution)]);
|
||||
}
|
||||
|
||||
function addProposal(uint32 contributorId, uint32 amount, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(ADD_PROPOSAL_ROLE) {
|
||||
require(IContributor(getContributorContract()).exists(contributorId), 'CONTRIBUTOR_NOT_FOUND');
|
||||
|
||||
uint32 proposalId = proposalsCount + 1;
|
||||
uint16 _votesNeeded = 1; //contributorsContract().coreContributorsCount() / 100 * 75;
|
||||
|
||||
Proposal storage p = proposals[proposalId];
|
||||
p.creatorAccount = msg.sender;
|
||||
p.contributorId = contributorId;
|
||||
p.amount = amount;
|
||||
p.hashDigest = hashDigest;
|
||||
p.hashFunction = hashFunction;
|
||||
p.hashSize = hashSize;
|
||||
p.votesCount = 0;
|
||||
p.votesNeeded = _votesNeeded;
|
||||
p.exists = true;
|
||||
|
||||
proposalsCount++;
|
||||
emit ProposalCreated(proposalId, msg.sender, p.contributorId, p.amount);
|
||||
}
|
||||
|
||||
function getProposal(uint32 proposalId) public view returns (uint32 id, address creatorAccount, uint32 contributorId, uint16 votesCount, uint16 votesNeeded, uint32 amount, bool executed, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint32[] voterIds, bool exists) {
|
||||
id = proposalId;
|
||||
Proposal storage p = proposals[id];
|
||||
return (
|
||||
id,
|
||||
p.creatorAccount,
|
||||
p.contributorId,
|
||||
p.votesCount,
|
||||
p.votesNeeded,
|
||||
p.amount,
|
||||
p.executed,
|
||||
p.hashDigest,
|
||||
p.hashFunction,
|
||||
p.hashSize,
|
||||
p.voterIds,
|
||||
p.exists
|
||||
);
|
||||
}
|
||||
|
||||
function vote(uint32 proposalId) public isInitialized auth(VOTE_PROPOSAL_ROLE) {
|
||||
Proposal storage p = proposals[proposalId];
|
||||
require(!p.executed, 'ALREADY_EXECUTED');
|
||||
uint32 voterId = IContributor(getContributorContract()).getContributorIdByAddress(msg.sender);
|
||||
require(p.votes[voterId] != true, 'ALREADY_VOTED');
|
||||
p.voterIds.push(voterId);
|
||||
p.votes[voterId] = true;
|
||||
|
||||
p.votesCount++;
|
||||
if (p.votesCount >= p.votesNeeded) {
|
||||
executeProposal(proposalId);
|
||||
}
|
||||
emit ProposalVoted(proposalId, voterId, p.votesCount);
|
||||
}
|
||||
|
||||
function batchVote(uint32[] _proposalIds) public isInitialized auth(VOTE_PROPOSAL_ROLE) {
|
||||
for (uint32 i = 0; i < _proposalIds.length; i++) {
|
||||
vote(_proposalIds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function executeProposal(uint32 proposalId) private {
|
||||
Proposal storage p = proposals[proposalId];
|
||||
require(!p.executed, 'ALREADY_EXECUTED');
|
||||
require(p.votesCount >= p.votesNeeded, 'MISSING_VOTES');
|
||||
|
||||
p.executed = true;
|
||||
IContribution(getContributionContract()).add(p.amount, p.contributorId, p.hashDigest, p.hashFunction, p.hashSize);
|
||||
emit ProposalExecuted(proposalId, p.contributorId, p.amount);
|
||||
}
|
||||
|
||||
}
|
||||
23
apps/proposal/contracts/misc/Migrations.sol
Normal file
23
apps/proposal/contracts/misc/Migrations.sol
Normal file
@@ -0,0 +1,23 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
contract Migrations {
|
||||
address public owner;
|
||||
uint public last_completed_migration;
|
||||
|
||||
modifier restricted() {
|
||||
if (msg.sender == owner) _;
|
||||
}
|
||||
|
||||
constructor() public {
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
function setCompleted(uint completed) public restricted {
|
||||
last_completed_migration = completed;
|
||||
}
|
||||
|
||||
function upgrade(address new_address) public restricted {
|
||||
Migrations upgraded = Migrations(new_address);
|
||||
upgraded.setCompleted(last_completed_migration);
|
||||
}
|
||||
}
|
||||
4
apps/proposal/manifest.json
Normal file
4
apps/proposal/manifest.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "Proposal",
|
||||
"description": "Kredits Proposal app"
|
||||
}
|
||||
5
apps/proposal/migrations/1_initial_migration.js
Normal file
5
apps/proposal/migrations/1_initial_migration.js
Normal file
@@ -0,0 +1,5 @@
|
||||
var Migrations = artifacts.require('./Migrations.sol')
|
||||
|
||||
module.exports = function (deployer) {
|
||||
deployer.deploy(Migrations)
|
||||
}
|
||||
28459
apps/proposal/package-lock.json
generated
Normal file
28459
apps/proposal/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
35
apps/proposal/package.json
Normal file
35
apps/proposal/package.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "kredits-proposal",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"@aragon/os": "^4.2.0",
|
||||
"@aragon/cli": "^5.9.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aragon/test-helpers": "^1.1.0",
|
||||
"eth-gas-reporter": "^0.2.0",
|
||||
"ganache-cli": "^6.4.3",
|
||||
"solidity-coverage": "^0.5.11"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "npm run start:aragon:ipfs",
|
||||
"start:aragon:ipfs": "aragon run",
|
||||
"start:aragon:http": "aragon run --http localhost:8001 --http-served-from ./dist",
|
||||
"start:app": "",
|
||||
"compile": "aragon contracts compile",
|
||||
"sync-assets": "",
|
||||
"build:app": "",
|
||||
"build:script": "",
|
||||
"build": "",
|
||||
"publish:patch": "aragon apm publish patch",
|
||||
"publish:minor": "aragon apm publish minor",
|
||||
"publish:major": "aragon apm publish major",
|
||||
"versions": "aragon apm versions",
|
||||
"test": "TRUFFLE_TEST=true PORT=7545 npm run ganache-cli:test",
|
||||
"test:gas": "GAS_REPORTER=true npm test",
|
||||
"coverage": "SOLIDITY_COVERAGE=true npm run ganache-cli:test",
|
||||
"ganache-cli:test": "./node_modules/@aragon/test-helpers/ganache-cli.sh"
|
||||
},
|
||||
"keywords": []
|
||||
}
|
||||
5
apps/proposal/test/app.js
Normal file
5
apps/proposal/test/app.js
Normal file
@@ -0,0 +1,5 @@
|
||||
// const Proposal = artifacts.require('Proposal.sol');
|
||||
|
||||
contract('Proposal', (_accounts) => {
|
||||
it('should be tested');
|
||||
});
|
||||
1
apps/proposal/truffle.js
Normal file
1
apps/proposal/truffle.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require("../../truffle.js");
|
||||
8145
apps/proposal/yarn.lock
Normal file
8145
apps/proposal/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
4
apps/token/.gitignore
vendored
Normal file
4
apps/token/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
node_modules
|
||||
build
|
||||
.cache
|
||||
dist
|
||||
14
apps/token/.ipfsignore
Normal file
14
apps/token/.ipfsignore
Normal file
@@ -0,0 +1,14 @@
|
||||
# Git files
|
||||
.gitignore
|
||||
|
||||
# Build files
|
||||
.cache
|
||||
node_modules
|
||||
build
|
||||
|
||||
# Lock files
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
# Others
|
||||
test
|
||||
1
apps/token/README.md
Normal file
1
apps/token/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# Kredits Token
|
||||
28
apps/token/arapp.json
Normal file
28
apps/token/arapp.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"roles": [
|
||||
{
|
||||
"name": "Mint token",
|
||||
"id": "MINT_TOKEN_ROLE",
|
||||
"params": []
|
||||
}
|
||||
],
|
||||
"environments": {
|
||||
"default": {
|
||||
"network": "development",
|
||||
"appName": "kredits-token.open.aragonpm.eth"
|
||||
},
|
||||
"rinkeby": {
|
||||
"registry": "0x98df287b6c145399aaa709692c8d308357bc085d",
|
||||
"appName": "kredits-token.open.aragonpm.eth",
|
||||
"wsRPC": "wss://rinkeby.eth.aragon.network/ws",
|
||||
"network": "rinkeby"
|
||||
},
|
||||
"mainnet": {
|
||||
"registry": "0x314159265dd8dbb310642f98f50c066173c1259b",
|
||||
"appName": "kredits-token.open.aragonpm.eth",
|
||||
"wsRPC": "wss://mainnet.eth.aragon.network/ws",
|
||||
"network": "mainnet"
|
||||
}
|
||||
},
|
||||
"path": "contracts/Token.sol"
|
||||
}
|
||||
173
apps/token/contracts/ERC20Token.sol
Normal file
173
apps/token/contracts/ERC20Token.sol
Normal file
@@ -0,0 +1,173 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "@aragon/os/contracts/lib/math/SafeMath.sol";
|
||||
|
||||
/**
|
||||
* beause ERC20.sol conflicts with the aragon ERC20.sol this is copied and modified from:
|
||||
* https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC20/ERC20.sol
|
||||
* @title Standard ERC20 token
|
||||
*
|
||||
* @dev Implementation of the basic standard token.
|
||||
* https://eips.ethereum.org/EIPS/eip-20
|
||||
* Originally based on code by FirstBlood:
|
||||
* https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
|
||||
*
|
||||
* This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for
|
||||
* all accounts just by listening to said events. Note that this isn't required by the specification, and other
|
||||
* compliant implementations may not do it.
|
||||
*/
|
||||
contract ERC20Token {
|
||||
using SafeMath for uint256;
|
||||
|
||||
mapping (address => uint256) public _balances;
|
||||
|
||||
mapping (address => mapping (address => uint256)) private _allowed;
|
||||
|
||||
uint256 public _totalSupply;
|
||||
|
||||
string public name;
|
||||
string public symbol;
|
||||
uint8 public decimals;
|
||||
|
||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||
|
||||
event Approval(address indexed owner, address indexed spender, uint256 value);
|
||||
|
||||
/**
|
||||
* @dev Total number of tokens in existence
|
||||
*/
|
||||
function totalSupply() public view returns (uint256) {
|
||||
return _totalSupply;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets the balance of the specified address.
|
||||
* @param owner The address to query the balance of.
|
||||
* @return A uint256 representing the amount owned by the passed address.
|
||||
*/
|
||||
function balanceOf(address owner) public view returns (uint256) {
|
||||
return _balances[owner];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Function to check the amount of tokens that an owner allowed to a spender.
|
||||
* @param owner address The address which owns the funds.
|
||||
* @param spender address The address which will spend the funds.
|
||||
* @return A uint256 specifying the amount of tokens still available for the spender.
|
||||
*/
|
||||
function allowance(address owner, address spender) public view returns (uint256) {
|
||||
return _allowed[owner][spender];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfer token to a specified address
|
||||
* @param to The address to transfer to.
|
||||
* @param value The amount to be transferred.
|
||||
*/
|
||||
function transfer(address to, uint256 value) public returns (bool) {
|
||||
_transfer(msg.sender, to, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
|
||||
* Beware that changing an allowance with this method brings the risk that someone may use both the old
|
||||
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
|
||||
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
|
||||
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
|
||||
* @param spender The address which will spend the funds.
|
||||
* @param value The amount of tokens to be spent.
|
||||
*/
|
||||
function approve(address spender, uint256 value) public returns (bool) {
|
||||
_approve(msg.sender, spender, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfer tokens from one address to another.
|
||||
* Note that while this function emits an Approval event, this is not required as per the specification,
|
||||
* and other compliant implementations may not emit the event.
|
||||
* @param from address The address which you want to send tokens from
|
||||
* @param to address The address which you want to transfer to
|
||||
* @param value uint256 the amount of tokens to be transferred
|
||||
*/
|
||||
function transferFrom(address from, address to, uint256 value) public returns (bool) {
|
||||
_transfer(from, to, value);
|
||||
_approve(from, msg.sender, _allowed[from][msg.sender].sub(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Increase the amount of tokens that an owner allowed to a spender.
|
||||
* approve should be called when _allowed[msg.sender][spender] == 0. To increment
|
||||
* allowed value is better to use this function to avoid 2 calls (and wait until
|
||||
* the first transaction is mined)
|
||||
* From MonolithDAO Token.sol
|
||||
* Emits an Approval event.
|
||||
* @param spender The address which will spend the funds.
|
||||
* @param addedValue The amount of tokens to increase the allowance by.
|
||||
*/
|
||||
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
|
||||
_approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Decrease the amount of tokens that an owner allowed to a spender.
|
||||
* approve should be called when _allowed[msg.sender][spender] == 0. To decrement
|
||||
* allowed value is better to use this function to avoid 2 calls (and wait until
|
||||
* the first transaction is mined)
|
||||
* From MonolithDAO Token.sol
|
||||
* Emits an Approval event.
|
||||
* @param spender The address which will spend the funds.
|
||||
* @param subtractedValue The amount of tokens to decrease the allowance by.
|
||||
*/
|
||||
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
|
||||
_approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfer token for a specified addresses
|
||||
* @param from The address to transfer from.
|
||||
* @param to The address to transfer to.
|
||||
* @param value The amount to be transferred.
|
||||
*/
|
||||
function _transfer(address from, address to, uint256 value) internal {
|
||||
require(to != address(0));
|
||||
|
||||
_balances[from] = _balances[from].sub(value);
|
||||
_balances[to] = _balances[to].add(value);
|
||||
emit Transfer(from, to, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Internal function that mints an amount of the token and assigns it to
|
||||
* an account. This encapsulates the modification of balances such that the
|
||||
* proper events are emitted.
|
||||
* @param account The account that will receive the created tokens.
|
||||
* @param value The amount that will be created.
|
||||
*/
|
||||
function _mint(address account, uint256 value) internal {
|
||||
require(account != address(0), 'invalid address');
|
||||
|
||||
_totalSupply = _totalSupply.add(value);
|
||||
_balances[account] = _balances[account].add(value);
|
||||
emit Transfer(address(0), account, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Approve an address to spend another addresses' tokens.
|
||||
* @param owner The address that owns the tokens.
|
||||
* @param spender The address that will spend the tokens.
|
||||
* @param value The number of tokens that can be spent.
|
||||
*/
|
||||
function _approve(address owner, address spender, uint256 value) internal {
|
||||
require(spender != address(0));
|
||||
require(owner != address(0));
|
||||
|
||||
_allowed[owner][spender] = value;
|
||||
emit Approval(owner, spender, value);
|
||||
}
|
||||
|
||||
}
|
||||
29
apps/token/contracts/Token.sol
Normal file
29
apps/token/contracts/Token.sol
Normal file
@@ -0,0 +1,29 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "@aragon/os/contracts/apps/AragonApp.sol";
|
||||
import "./ERC20Token.sol";
|
||||
|
||||
contract Token is ERC20Token, AragonApp {
|
||||
bytes32 public constant MINT_TOKEN_ROLE = keccak256("MINT_TOKEN_ROLE");
|
||||
|
||||
// ensure alphabetic order
|
||||
enum Apps { Contribution, Contributor, Proposal, Token }
|
||||
bytes32[4] public appIds;
|
||||
|
||||
event LogMint(address indexed recipient, uint256 amount, uint32 contributionId);
|
||||
|
||||
function initialize(bytes32[4] _appIds) public onlyInit {
|
||||
appIds = _appIds;
|
||||
name = 'Kredits';
|
||||
symbol = '₭S';
|
||||
decimals = 18;
|
||||
initialized();
|
||||
}
|
||||
|
||||
function mintFor(address contributorAccount, uint256 amount, uint32 contributionId) public isInitialized auth(MINT_TOKEN_ROLE) {
|
||||
uint256 amountInWei = amount.mul(1 ether);
|
||||
_mint(contributorAccount, amountInWei);
|
||||
emit LogMint(contributorAccount, amount, contributionId);
|
||||
}
|
||||
|
||||
}
|
||||
23
apps/token/contracts/misc/Migrations.sol
Normal file
23
apps/token/contracts/misc/Migrations.sol
Normal file
@@ -0,0 +1,23 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
contract Migrations {
|
||||
address public owner;
|
||||
uint public last_completed_migration;
|
||||
|
||||
modifier restricted() {
|
||||
if (msg.sender == owner) _;
|
||||
}
|
||||
|
||||
constructor() public {
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
function setCompleted(uint completed) public restricted {
|
||||
last_completed_migration = completed;
|
||||
}
|
||||
|
||||
function upgrade(address new_address) public restricted {
|
||||
Migrations upgraded = Migrations(new_address);
|
||||
upgraded.setCompleted(last_completed_migration);
|
||||
}
|
||||
}
|
||||
4
apps/token/manifest.json
Normal file
4
apps/token/manifest.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "Token",
|
||||
"description": "Kredits Token app"
|
||||
}
|
||||
5
apps/token/migrations/1_initial_migration.js
Normal file
5
apps/token/migrations/1_initial_migration.js
Normal file
@@ -0,0 +1,5 @@
|
||||
var Migrations = artifacts.require('./Migrations.sol')
|
||||
|
||||
module.exports = function (deployer) {
|
||||
deployer.deploy(Migrations)
|
||||
}
|
||||
5
apps/token/migrations/2_deploy_contracts.js
Normal file
5
apps/token/migrations/2_deploy_contracts.js
Normal file
@@ -0,0 +1,5 @@
|
||||
var Token = artifacts.require('Token.sol')
|
||||
|
||||
module.exports = function (deployer) {
|
||||
deployer.deploy(Token)
|
||||
}
|
||||
28459
apps/token/package-lock.json
generated
Normal file
28459
apps/token/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
35
apps/token/package.json
Normal file
35
apps/token/package.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "kredits-token",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"@aragon/os": "^4.2.0",
|
||||
"@aragon/cli": "^5.9.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aragon/test-helpers": "^1.1.0",
|
||||
"eth-gas-reporter": "^0.2.0",
|
||||
"ganache-cli": "^6.4.3",
|
||||
"solidity-coverage": "^0.5.11"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "npm run start:aragon:ipfs",
|
||||
"start:aragon:ipfs": "aragon run",
|
||||
"start:aragon:http": "aragon run --http localhost:8001 --http-served-from ./dist",
|
||||
"start:app": "",
|
||||
"compile": "aragon contracts compile",
|
||||
"sync-assets": "",
|
||||
"build:app": "",
|
||||
"build:script": "",
|
||||
"build": "",
|
||||
"publish:patch": "aragon apm publish patch",
|
||||
"publish:minor": "aragon apm publish minor",
|
||||
"publish:major": "aragon apm publish major",
|
||||
"versions": "aragon apm versions",
|
||||
"test": "TRUFFLE_TEST=true PORT=7545 npm run ganache-cli:test",
|
||||
"test:gas": "GAS_REPORTER=true npm test",
|
||||
"coverage": "SOLIDITY_COVERAGE=true npm run ganache-cli:test",
|
||||
"ganache-cli:test": "./node_modules/@aragon/test-helpers/ganache-cli.sh"
|
||||
},
|
||||
"keywords": []
|
||||
}
|
||||
5
apps/token/test/app.js
Normal file
5
apps/token/test/app.js
Normal file
@@ -0,0 +1,5 @@
|
||||
// const Token = artifacts.require('Token.sol');
|
||||
|
||||
contract('Token', (_accounts) => {
|
||||
it('should be tested');
|
||||
});
|
||||
1
apps/token/truffle.js
Normal file
1
apps/token/truffle.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require("../../truffle.js");
|
||||
8145
apps/token/yarn.lock
Normal file
8145
apps/token/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
60
arapp.json
Normal file
60
arapp.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"roles": [
|
||||
{
|
||||
"name": "Add contributions",
|
||||
"id": "ADD_CONTRIBUTION_ROLE",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"name": "Veto contributions",
|
||||
"id": "VETO_CONTRIBUTION_ROLE",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"name": "Manage contributors",
|
||||
"id": "MANAGE_CONTRIBUTORS_ROLE",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"name": "Mint token",
|
||||
"id": "MINT_TOKEN_ROLE",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"name": "Add proposal",
|
||||
"id": "ADD_PROPOSAL_ROLE",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"name": "Vote proposal",
|
||||
"id": "VOTE_PROPOSAL_ROLE",
|
||||
"params": []
|
||||
}
|
||||
],
|
||||
"environments": {
|
||||
"development": {
|
||||
"network": "development",
|
||||
"apm": "open.aragonpm.eth",
|
||||
"registry": "0x5f6f7e8cc7346a11ca2def8f827b7a0b612c56a1",
|
||||
"appName": "dummy.open.aragonpm.eth"
|
||||
},
|
||||
"rinkeby": {
|
||||
"network": "rinkeby",
|
||||
"registry": "0x98Df287B6C145399Aaa709692c8D308357bC085D",
|
||||
"wsRPC": "wss://rinkeby.eth.aragon.network/ws",
|
||||
"daoFactory": "0x2298d27a9b847c681d2b2c2828ab9d79013f5f1d",
|
||||
"appName": "dummy.open.aragonpm.eth",
|
||||
"apm": "open.aragonpm.eth"
|
||||
},
|
||||
"kovan": {
|
||||
"network": "kovan",
|
||||
"appName": "dummy.aragonpm.eth"
|
||||
},
|
||||
"default": {
|
||||
"network": "development",
|
||||
"appName": "dummy.aragonpm.eth",
|
||||
"apm": "open.aragonpm.eth"
|
||||
}
|
||||
},
|
||||
"path": "contracts/misc/DummyApp.sol"
|
||||
}
|
||||
@@ -1,9 +1,48 @@
|
||||
let contractCalls = [
|
||||
['Contributor', 'add', [{ account: '0x7e8f313c56f809188313aa274fa67ee58c31515d', name: 'bumi', isCore: true, kind: 'preson', url: '', github_username: 'bumi', github_uid: 318, wiki_username: 'bumi' }, {gasLimit: 200000}]],
|
||||
['Contributor', 'add', [{ account: '0xa502eb4021f3b9ab62f75b57a94e1cfbf81fd827', name: 'raucau', isCore: true, kind: 'person', url: '', github_username: 'skddc', github_uid: 842, wiki_username: 'raucau' }, {gasLimit: 200000}]],
|
||||
['Operator', 'addProposal', [{ contributorId: 2, amount: 42, kind: 'code', description: 'runs the seeds', url: '' }, {gasLimit: 350000}]],
|
||||
['Operator', 'addProposal', [{ contributorId: 3, amount: 23, kind: 'code', description: 'runs the seeds', url: '' }, {gasLimit: 350000}]],
|
||||
['Operator', 'addProposal', [{contributorId: 3, amount: 100, kind: 'code', description: 'hacks on kredits', url: '' }, {gasLimit: 350000}]],
|
||||
['Operator', 'vote', ['1', {gasLimit: 250000}]]
|
||||
const contractCalls = [
|
||||
['Contributor', 'add', [{
|
||||
account: '0x7e8f313c56f809188313aa274fa67ee58c31515d',
|
||||
name: 'bumi',
|
||||
kind: 'person',
|
||||
url: '',
|
||||
github_username: 'bumi',
|
||||
github_uid: 318,
|
||||
gitea_username: 'bumi',
|
||||
wiki_username: 'Bumi',
|
||||
}, { gasLimit: 200000 }]],
|
||||
|
||||
['Contributor', 'add', [{
|
||||
account: '0x49575f3DD9a0d60aE661BC992f72D837A77f05Bc',
|
||||
name: 'raucao',
|
||||
kind: 'person',
|
||||
url: '',
|
||||
github_username: 'skddc',
|
||||
github_uid: 842,
|
||||
gitea_username: 'raucao',
|
||||
wiki_username: 'Basti',
|
||||
}, { gasLimit: 200000 }]],
|
||||
|
||||
['Contributor', 'add', [{
|
||||
account: '0xF722709ECC3B05c19d02E82a2a4A4021B8F48C62',
|
||||
name: 'Manuel',
|
||||
kind: 'person',
|
||||
url: '',
|
||||
github_username: 'fsmanuel',
|
||||
github_uid: 54812,
|
||||
wiki_username: 'Manuel',
|
||||
}, { gasLimit: 200000 }]],
|
||||
|
||||
['Proposal', 'add', [{ contributorId: 1, contributorIpfsHash: 'QmWKCYGr2rSf6abUPaTYqf98urvoZxGrb7dbspFZA6oyVF', date: '2019-04-09', amount: 500, kind: 'dev', description: '[67P/kredits-contracts] Ran the seeds', url: '' }, { gasLimit: 350000 }]],
|
||||
['Proposal', 'add', [{ contributorId: 2, contributorIpfsHash: 'QmcHzEeAM26HV2zHTf5HnZrCtCtGdEccL5kUtDakAB7ozB', date: '2019-04-10', amount: 500, kind: 'dev', description: '[67P/kredits-contracts] Ran the seeds', url: '' }, { gasLimit: 350000 }]],
|
||||
['Proposal', 'add', [{ contributorId: 2, contributorIpfsHash: 'QmcHzEeAM26HV2zHTf5HnZrCtCtGdEccL5kUtDakAB7ozB', date: '2019-04-11', amount: 500, kind: 'dev', description: '[67P/kredits-contracts] Hacked on kredits', url: '' }, { gasLimit: 350000 }]],
|
||||
['Proposal', 'vote', [1, { gasLimit: 550000 }]],
|
||||
['Contribution', 'add', [{ contributorId: 1, contributorIpfsHash: 'QmWKCYGr2rSf6abUPaTYqf98urvoZxGrb7dbspFZA6oyVF', date: '2019-04-11', amount: 5000, kind: 'dev', description: '[67P/kredits-contracts] Introduce contribution token', url: '' }, { gasLimit: 350000 }]],
|
||||
['Contribution', 'add', [{ contributorId: 2, contributorIpfsHash: 'QmcHzEeAM26HV2zHTf5HnZrCtCtGdEccL5kUtDakAB7ozB', date: '2019-04-11', amount: 1500, kind: 'dev', description: '[67P/kredits-web] Reviewed stuff', url: '' }, { gasLimit: 350000 }]],
|
||||
['Contribution', 'claim', [1, { gasLimit: 300000 }]],
|
||||
];
|
||||
module.exports = { contractCalls };
|
||||
|
||||
const funds = [
|
||||
'0x7e8f313c56f809188313aa274fa67ee58c31515d',
|
||||
'0xa502eb4021f3b9ab62f75b57a94e1cfbf81fd827',
|
||||
];
|
||||
|
||||
module.exports = { contractCalls, funds };
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
// import basic ERC20 details to be able to call balanceOf
|
||||
import 'zeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol';
|
||||
import './upgradeable/Upgradeable.sol';
|
||||
|
||||
contract Contributors is Upgradeable {
|
||||
|
||||
struct Contributor {
|
||||
address account;
|
||||
bytes32 ipfsHash;
|
||||
uint8 hashFunction;
|
||||
uint8 hashSize;
|
||||
bool isCore;
|
||||
bool exists;
|
||||
}
|
||||
|
||||
mapping (address => uint) public contributorIds;
|
||||
mapping (uint => Contributor) public contributors;
|
||||
uint256 public contributorsCount;
|
||||
|
||||
event ContributorProfileUpdated(uint id, bytes32 oldIpfsHash, bytes32 newIpfsHash);
|
||||
event ContributorAccountUpdated(uint id, address oldAccount, address newAccount);
|
||||
event ContributorAdded(uint id, address account);
|
||||
|
||||
modifier onlyCoreOrOperator() {
|
||||
require(msg.sender == registry.getProxyFor('Operator') || addressIsCore(msg.sender));
|
||||
_;
|
||||
}
|
||||
|
||||
function initialize(address sender) public payable {
|
||||
require(msg.sender == address(registry));
|
||||
uint _id = 1;
|
||||
Contributor storage c = contributors[_id];
|
||||
c.exists = true;
|
||||
c.isCore = true;
|
||||
c.account = sender;
|
||||
contributorIds[sender] = _id;
|
||||
contributorsCount += 1;
|
||||
}
|
||||
|
||||
function coreContributorsCount() view public returns (uint) {
|
||||
uint count = 0;
|
||||
for (uint256 i = 1; i <= contributorsCount; i++) {
|
||||
if (contributors[i].isCore) {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
function updateContributorAccount(uint id, address oldAccount, address newAccount) public onlyCoreOrOperator {
|
||||
contributorIds[oldAccount] = 0;
|
||||
contributorIds[newAccount] = id;
|
||||
contributors[id].account = newAccount;
|
||||
ContributorAccountUpdated(id, oldAccount, newAccount);
|
||||
}
|
||||
|
||||
function updateContributorIpfsHash(uint id, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize) public onlyCoreOrOperator {
|
||||
Contributor storage c = contributors[id];
|
||||
bytes32 oldIpfsHash = c.ipfsHash;
|
||||
c.ipfsHash = ipfsHash;
|
||||
c.hashFunction = hashFunction;
|
||||
c.hashSize = hashSize;
|
||||
|
||||
ContributorProfileUpdated(id, oldIpfsHash, c.ipfsHash);
|
||||
}
|
||||
|
||||
function addContributor(address account, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize, bool isCore) public onlyCoreOrOperator {
|
||||
require(!addressExists(account));
|
||||
uint _id = contributorsCount + 1;
|
||||
assert(!contributors[_id].exists); // this can not be acually
|
||||
Contributor storage c = contributors[_id];
|
||||
c.exists = true;
|
||||
c.isCore = isCore;
|
||||
c.ipfsHash = ipfsHash;
|
||||
c.hashFunction = hashFunction;
|
||||
c.hashSize = hashSize;
|
||||
c.account = account;
|
||||
contributorIds[account] = _id;
|
||||
|
||||
contributorsCount += 1;
|
||||
ContributorAdded(_id, account);
|
||||
}
|
||||
|
||||
function isCore(uint id) view public returns (bool) {
|
||||
return contributors[id].isCore;
|
||||
}
|
||||
|
||||
function exists(uint id) view public returns (bool) {
|
||||
return contributors[id].exists;
|
||||
}
|
||||
|
||||
function addressIsCore(address account) view public returns (bool) {
|
||||
return getContributorByAddress(account).isCore;
|
||||
}
|
||||
|
||||
function addressExists(address account) view public returns (bool) {
|
||||
return getContributorByAddress(account).exists;
|
||||
}
|
||||
|
||||
function getContributorIdByAddress(address account) view public returns (uint) {
|
||||
return contributorIds[account];
|
||||
}
|
||||
|
||||
function getContributorAddressById(uint id) view public returns (address) {
|
||||
return contributors[id].account;
|
||||
}
|
||||
|
||||
function getContributorByAddress(address account) internal view returns (Contributor) {
|
||||
uint id = contributorIds[account];
|
||||
return contributors[id];
|
||||
}
|
||||
|
||||
function getContributorById(uint _id) public view returns (uint id, address account, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize, bool isCore, uint balance, bool exists ) {
|
||||
id = _id;
|
||||
Contributor storage c = contributors[_id];
|
||||
account = c.account;
|
||||
ipfsHash = c.ipfsHash;
|
||||
hashFunction = c.hashFunction;
|
||||
hashSize = c.hashSize;
|
||||
isCore = c.isCore;
|
||||
exists = c.exists;
|
||||
|
||||
ERC20Basic token = ERC20Basic(registry.getProxyFor('Token'));
|
||||
balance = token.balanceOf(account);
|
||||
}
|
||||
}
|
||||
90
contracts/KreditsKit.sol
Normal file
90
contracts/KreditsKit.sol
Normal file
@@ -0,0 +1,90 @@
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "@aragon/os/contracts/apps/AragonApp.sol";
|
||||
import "@aragon/os/contracts/kernel/Kernel.sol";
|
||||
import "@aragon/os/contracts/acl/ACL.sol";
|
||||
|
||||
import "@aragon/kits-base/contracts/KitBase.sol";
|
||||
|
||||
import "../apps/contribution/contracts/Contribution.sol";
|
||||
import "../apps/contributor/contracts/Contributor.sol";
|
||||
import "../apps/token/contracts/Token.sol";
|
||||
import "../apps/proposal/contracts/Proposal.sol";
|
||||
|
||||
contract KreditsKit is KitBase {
|
||||
|
||||
// ensure alphabetic order
|
||||
enum Apps { Contribution, Contributor, Proposal, Token }
|
||||
bytes32[4] public appIds;
|
||||
|
||||
event DeployInstance(address dao);
|
||||
event InstalledApp(address dao, address appProxy, bytes32 appId);
|
||||
|
||||
constructor (DAOFactory _fac, ENS _ens, bytes32[4] _appIds) public KitBase(_fac, _ens) {
|
||||
appIds = _appIds;
|
||||
}
|
||||
|
||||
function newInstance() public returns (Kernel dao) {
|
||||
address root = msg.sender;
|
||||
dao = fac.newDAO(this);
|
||||
ACL acl = ACL(dao.acl());
|
||||
|
||||
acl.createPermission(this, dao, dao.APP_MANAGER_ROLE(), this);
|
||||
|
||||
Contributor contributor = Contributor(_installApp(dao, appIds[uint8(Apps.Contributor)]));
|
||||
contributor.initialize(root, appIds);
|
||||
acl.createPermission(root, contributor, contributor.MANAGE_CONTRIBUTORS_ROLE(), this);
|
||||
|
||||
Token token = Token(_installApp(dao, appIds[uint8(Apps.Token)]));
|
||||
token.initialize(appIds);
|
||||
|
||||
Contribution contribution = Contribution(_installApp(dao, appIds[uint8(Apps.Contribution)]));
|
||||
contribution.initialize(appIds);
|
||||
|
||||
Proposal proposal = Proposal(_installApp(dao, appIds[uint8(Apps.Proposal)]));
|
||||
proposal.initialize(appIds);
|
||||
|
||||
acl.createPermission(root, contribution, contribution.ADD_CONTRIBUTION_ROLE(), this);
|
||||
acl.createPermission(root, contribution, contribution.VETO_CONTRIBUTION_ROLE(), this);
|
||||
acl.grantPermission(proposal, contribution, contribution.ADD_CONTRIBUTION_ROLE());
|
||||
|
||||
uint256[] memory params = new uint256[](1);
|
||||
params[0] = uint256(203) << 248 | uint256(1) << 240 | uint240(contributor);
|
||||
acl.grantPermissionP(acl.ANY_ENTITY(), contribution, contribution.ADD_CONTRIBUTION_ROLE(), params);
|
||||
acl.grantPermissionP(acl.ANY_ENTITY(), contribution, contribution.VETO_CONTRIBUTION_ROLE(), params);
|
||||
acl.grantPermissionP(acl.ANY_ENTITY(), contributor, contributor.MANAGE_CONTRIBUTORS_ROLE(), params);
|
||||
|
||||
//acl.setPermissionManager(this, proposal, proposal.VOTE_PROPOSAL_ROLE();
|
||||
acl.createPermission(root, proposal, proposal.VOTE_PROPOSAL_ROLE(), this);
|
||||
acl.grantPermissionP(acl.ANY_ENTITY(), proposal, proposal.VOTE_PROPOSAL_ROLE(), params);
|
||||
|
||||
acl.createPermission(root, proposal, proposal.ADD_PROPOSAL_ROLE(), this);
|
||||
//acl.grantPermissionP(address(-1), proposal, proposal.ADD_PROPOSAL_ROLE(), params);
|
||||
acl.grantPermission(acl.ANY_ENTITY(), proposal, proposal.ADD_PROPOSAL_ROLE());
|
||||
|
||||
acl.setPermissionManager(root, proposal, proposal.VOTE_PROPOSAL_ROLE());
|
||||
acl.setPermissionManager(root, proposal, proposal.ADD_PROPOSAL_ROLE());
|
||||
acl.setPermissionManager(root, contribution, contribution.ADD_CONTRIBUTION_ROLE());
|
||||
acl.setPermissionManager(root, contribution, contribution.VETO_CONTRIBUTION_ROLE());
|
||||
acl.setPermissionManager(root, contributor, contributor.MANAGE_CONTRIBUTORS_ROLE());
|
||||
|
||||
acl.createPermission(root, token, token.MINT_TOKEN_ROLE(), this);
|
||||
acl.grantPermission(contribution, token, token.MINT_TOKEN_ROLE());
|
||||
acl.setPermissionManager(root, token, token.MINT_TOKEN_ROLE());
|
||||
|
||||
|
||||
cleanupDAOPermissions(dao, acl, root);
|
||||
|
||||
emit DeployInstance(dao);
|
||||
return dao;
|
||||
}
|
||||
|
||||
function _installApp(Kernel _dao, bytes32 _appId) internal returns (AragonApp) {
|
||||
address baseAppAddress = latestVersionAppBase(_appId);
|
||||
require(baseAppAddress != address(0), "App should be deployed");
|
||||
AragonApp appProxy = AragonApp(_dao.newAppInstance(_appId, baseAppAddress, new bytes(0), true));
|
||||
|
||||
emit InstalledApp(_dao, appProxy, _appId);
|
||||
return appProxy;
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
// ToDo: only load interfaces
|
||||
import './Token.sol';
|
||||
import './Contributors.sol';
|
||||
|
||||
contract Operator is Upgradeable {
|
||||
|
||||
struct Proposal {
|
||||
address creatorAccount;
|
||||
uint contributorId;
|
||||
uint votesCount;
|
||||
uint votesNeeded;
|
||||
uint256 amount;
|
||||
bool executed;
|
||||
bytes32 ipfsHash;
|
||||
uint8 hashFunction;
|
||||
uint8 hashSize;
|
||||
uint256[] voterIds;
|
||||
mapping (uint256 => bool) votes;
|
||||
bool exists;
|
||||
}
|
||||
|
||||
mapping(uint256 => Proposal) public proposals;
|
||||
uint256 public proposalsCount;
|
||||
|
||||
event ProposalCreated(uint256 id, address creatorAccount, uint256 contributorId, uint256 amount);
|
||||
event ProposalVoted(uint256 id, uint256 voterId, uint256 totalVotes);
|
||||
event ProposalExecuted(uint256 id, uint256 contributorId, uint256 amount);
|
||||
|
||||
modifier coreOnly() {
|
||||
require(contributorsContract().addressIsCore(msg.sender));
|
||||
_;
|
||||
}
|
||||
modifier contributorOnly() {
|
||||
require(contributorsContract().addressExists(msg.sender));
|
||||
_;
|
||||
}
|
||||
modifier noEther() {
|
||||
require(msg.value == 0);
|
||||
_;
|
||||
}
|
||||
|
||||
function contributorsContract() view public returns (Contributors) {
|
||||
return Contributors(registry.getProxyFor('Contributors'));
|
||||
}
|
||||
function tokenContract() view public returns (Token) {
|
||||
return Token(registry.getProxyFor('Token'));
|
||||
}
|
||||
|
||||
function contributorsCount() view public returns (uint) {
|
||||
return contributorsContract().contributorsCount();
|
||||
}
|
||||
function coreContributorsCount() view public returns (uint) {
|
||||
return contributorsContract().coreContributorsCount();
|
||||
}
|
||||
|
||||
function addProposal(uint contributorId, uint256 amount, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize) public {
|
||||
require(contributorsContract().exists(contributorId));
|
||||
|
||||
uint256 proposalId = proposalsCount + 1;
|
||||
uint256 _votesNeeded = contributorsContract().coreContributorsCount() / 100 * 75;
|
||||
|
||||
var p = proposals[proposalId];
|
||||
p.creatorAccount = msg.sender;
|
||||
p.contributorId = contributorId;
|
||||
p.amount = amount;
|
||||
p.ipfsHash = ipfsHash;
|
||||
p.hashFunction = hashFunction;
|
||||
p.hashSize = hashSize;
|
||||
p.votesCount = 0;
|
||||
p.votesNeeded = _votesNeeded;
|
||||
p.exists = true;
|
||||
|
||||
proposalsCount++;
|
||||
ProposalCreated(proposalId, msg.sender, p.contributorId, p.amount);
|
||||
}
|
||||
|
||||
function getProposal(uint proposalId) public view returns (uint256 id, address creatorAccount, uint256 contributorId, uint256 votesCount, uint256 votesNeeded, uint256 amount, bool executed, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize, uint256[] voterIds, bool exists) {
|
||||
id = proposalId;
|
||||
Proposal storage p = proposals[id];
|
||||
return (
|
||||
id,
|
||||
p.creatorAccount,
|
||||
p.contributorId,
|
||||
p.votesCount,
|
||||
p.votesNeeded,
|
||||
p.amount,
|
||||
p.executed,
|
||||
p.ipfsHash,
|
||||
p.hashFunction,
|
||||
p.hashSize,
|
||||
p.voterIds,
|
||||
p.exists
|
||||
);
|
||||
}
|
||||
|
||||
function vote(uint256 proposalId) public coreOnly {
|
||||
var p = proposals[proposalId];
|
||||
require(!p.executed);
|
||||
uint256 voterId = contributorsContract().getContributorIdByAddress(msg.sender);
|
||||
require(p.votes[voterId] != true);
|
||||
p.voterIds.push(voterId);
|
||||
p.votes[voterId] = true;
|
||||
|
||||
p.votesCount++;
|
||||
if (p.votesCount >= p.votesNeeded) {
|
||||
executeProposal(proposalId);
|
||||
}
|
||||
ProposalVoted(proposalId, voterId, p.votesCount);
|
||||
}
|
||||
|
||||
function executeProposal(uint proposalId) private {
|
||||
var p = proposals[proposalId];
|
||||
require(!p.executed);
|
||||
require(p.votesCount >= p.votesNeeded);
|
||||
address recipientAddress = contributorsContract().getContributorAddressById(p.contributorId);
|
||||
tokenContract().mintFor(recipientAddress, p.amount, proposalId);
|
||||
p.executed = true;
|
||||
ProposalExecuted(proposalId, p.contributorId, p.amount);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
import 'zeppelin-solidity/contracts/token/ERC20/BasicToken.sol';
|
||||
import './upgradeable/Upgradeable.sol';
|
||||
|
||||
contract Token is Upgradeable, BasicToken {
|
||||
string public name;
|
||||
string public symbol;
|
||||
uint8 public decimals;
|
||||
|
||||
event LogMint(address indexed recipient, uint256 amount, uint256 proposalId);
|
||||
|
||||
function initialize(address sender) public payable {
|
||||
require(msg.sender == address(registry));
|
||||
name = 'Kredits';
|
||||
symbol = 'K';
|
||||
decimals = 18;
|
||||
}
|
||||
|
||||
function mintFor(address contributorAccount, uint256 amount, uint proposalId) onlyRegistryContractFor('Operator') public {
|
||||
totalSupply_ = totalSupply_.add(amount);
|
||||
balances[contributorAccount] = balances[contributorAccount].add(amount);
|
||||
|
||||
LogMint(contributorAccount, amount, proposalId);
|
||||
}
|
||||
|
||||
}
|
||||
13
contracts/misc/APMNamehashOpen.sol
Normal file
13
contracts/misc/APMNamehashOpen.sol
Normal file
@@ -0,0 +1,13 @@
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "@aragon/os/contracts/apm/APMNamehash.sol";
|
||||
|
||||
|
||||
contract APMNamehashOpen is APMNamehash {
|
||||
bytes32 public constant OPEN_TITLE = keccak256("open");
|
||||
bytes32 public constant OPEN_APM_NODE = keccak256(abi.encodePacked(APM_NODE, OPEN_TITLE));
|
||||
|
||||
function apmNamehashOpen(string name) internal pure returns (bytes32) {
|
||||
return keccak256(abi.encodePacked(OPEN_APM_NODE, keccak256(name)));
|
||||
}
|
||||
}
|
||||
16
contracts/misc/DummyApp.sol
Normal file
16
contracts/misc/DummyApp.sol
Normal file
@@ -0,0 +1,16 @@
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "@aragon/os/contracts/apps/AragonApp.sol";
|
||||
|
||||
|
||||
// This is a "Dummy" app which's only purpose to exist is because
|
||||
// Aragon's CLI still doesn't support running a Kit inside a project
|
||||
// which isn't considered to be a "valid" Aragon project.
|
||||
// It requires us to have an arrap.json file pointing to the contract
|
||||
// and a manifest.json file which describes the front-end structure.
|
||||
contract DummyApp is AragonApp {
|
||||
function initialize() public onlyInit {
|
||||
initialized();
|
||||
}
|
||||
}
|
||||
|
||||
23
contracts/misc/Migrations.sol
Normal file
23
contracts/misc/Migrations.sol
Normal file
@@ -0,0 +1,23 @@
|
||||
pragma solidity ^0.4.4;
|
||||
|
||||
contract Migrations {
|
||||
address public owner;
|
||||
uint public last_completed_migration;
|
||||
|
||||
modifier restricted() {
|
||||
if (msg.sender == owner) _;
|
||||
}
|
||||
|
||||
function constructor() public {
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
function setCompleted(uint completed) public restricted {
|
||||
last_completed_migration = completed;
|
||||
}
|
||||
|
||||
function upgrade(address new_address) public restricted {
|
||||
Migrations upgraded = Migrations(new_address);
|
||||
upgraded.setCompleted(last_completed_migration);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
/**
|
||||
* @title IRegistry
|
||||
* @dev This contract represents the interface of a registry contract
|
||||
*/
|
||||
interface IRegistry {
|
||||
/**
|
||||
* @dev This event will be emitted every time a new proxy is created
|
||||
* @param name of the contract, as specified in the registry
|
||||
* @param proxy representing the address of the proxy created
|
||||
*/
|
||||
event ProxyCreated(string name, address proxy);
|
||||
|
||||
/**
|
||||
* @dev This event will be emitted every time a new implementation is registered
|
||||
* @param name of the contract, as specified in the registry
|
||||
* @param version representing the version name of the registered implementation
|
||||
* @param implementation representing the address of the registered implementation
|
||||
*/
|
||||
event VersionAdded(string name, uint version, address implementation);
|
||||
|
||||
/**
|
||||
* @dev This event will be emitted every time a proxy is upgraded to a new version
|
||||
* @param name of the contract, as specified in the registry
|
||||
* @param version representing the version name of the registered implementation
|
||||
*/
|
||||
event ProxyImplementationUpgraded(string name, uint version);
|
||||
|
||||
/**
|
||||
* @dev Registers a new version with its implementation address
|
||||
* @param name of the contract, as specified in the registry
|
||||
* @param implementation representing the address of the new implementation to be registered
|
||||
*/
|
||||
function addVersion(string name, address implementation) public;
|
||||
|
||||
/**
|
||||
* @dev Tells the address of the implementation for a given version
|
||||
* @param name of the contract, as specified in the registry
|
||||
* @param version to query the implementation of
|
||||
* @return address of the implementation registered for the given version
|
||||
*/
|
||||
function getVersion(string name, uint version) public view returns (address);
|
||||
|
||||
/**
|
||||
* @dev Tells the latest address of the implementation
|
||||
* @param name of the contract, as specified in the registry
|
||||
* @return address of the implementation registered for the latest version
|
||||
*/
|
||||
function getLatestVersion(string name) public view returns (address);
|
||||
|
||||
function getProxyFor(string name) public view returns (address);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
/**
|
||||
* @title Proxy
|
||||
* @dev Gives the possibility to delegate any call to a foreign implementation.
|
||||
*/
|
||||
contract Proxy {
|
||||
|
||||
/**
|
||||
* @dev Tells the address of the implementation where every call will be delegated.
|
||||
* @return address of the implementation to which it will be delegated
|
||||
*/
|
||||
function implementation() public view returns (address);
|
||||
|
||||
/**
|
||||
* @dev Fallback function allowing to perform a delegatecall to the given implementation.
|
||||
* This function will return whatever the implementation call returns
|
||||
*/
|
||||
function () payable public {
|
||||
address _impl = implementation();
|
||||
require(_impl != address(0));
|
||||
bytes memory data = msg.data;
|
||||
|
||||
assembly {
|
||||
let result := delegatecall(gas, _impl, add(data, 0x20), mload(data), 0, 0)
|
||||
let size := returndatasize
|
||||
|
||||
let ptr := mload(0x40)
|
||||
returndatacopy(ptr, 0, size)
|
||||
|
||||
switch result
|
||||
case 0 { revert(ptr, size) }
|
||||
default { return(ptr, size) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
import './IRegistry.sol';
|
||||
import './Upgradeable.sol';
|
||||
import './UpgradeabilityProxy.sol';
|
||||
|
||||
/**
|
||||
* @title Registry
|
||||
* @dev This contract works as a registry of versions, it holds the implementations for the registered versions.
|
||||
*/
|
||||
contract Registry is IRegistry {
|
||||
// mapping of contract names to versions to implementation
|
||||
// "Token" => "1.0.0" => "0x123"
|
||||
mapping(bytes32 => mapping(uint => address)) public versions;
|
||||
|
||||
// current version for a certain contract
|
||||
mapping(bytes32 => uint) public currentVersions;
|
||||
|
||||
// mapping of the contract names to the proxy addresses
|
||||
mapping(bytes32 => address) public proxies;
|
||||
|
||||
/**
|
||||
* @dev Registers a new version with its implementation address
|
||||
* @param name of the contract
|
||||
* @param implementation representing the address of the new implementation to be registered
|
||||
*/
|
||||
function addVersion(string name, address implementation) public {
|
||||
bytes32 key = keccak256(name);
|
||||
currentVersions[key] = currentVersions[key] + 1;
|
||||
uint version = currentVersions[key];
|
||||
require(versions[key][version] == 0x0);
|
||||
versions[key][version] = implementation;
|
||||
VersionAdded(name, version, implementation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Tells the address of the implementation for a given version
|
||||
* @param name of the contract
|
||||
* @param version to query the implementation of
|
||||
* @return address of the implementation registered for the given version
|
||||
*/
|
||||
function getVersion(string name, uint version) public view returns (address) {
|
||||
bytes32 key = keccak256(name);
|
||||
return versions[key][version];
|
||||
}
|
||||
|
||||
function getLatestVersion(string name) public view returns (address) {
|
||||
bytes32 key = keccak256(name);
|
||||
uint current = currentVersions[key];
|
||||
return getVersion(name, current);
|
||||
}
|
||||
|
||||
function getProxyFor(string name) public view returns (address) {
|
||||
bytes32 key = keccak256(name);
|
||||
return proxies[key];
|
||||
}
|
||||
|
||||
function upgrade(string name, uint version) public {
|
||||
bytes32 key = keccak256(name);
|
||||
UpgradeabilityProxy(proxies[key]).upgradeTo(version);
|
||||
ProxyImplementationUpgraded(name, version);
|
||||
}
|
||||
|
||||
function upgradeToLatest(string name) public {
|
||||
bytes32 key = keccak256(name);
|
||||
uint current = currentVersions[key];
|
||||
upgrade(name, current);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Creates an upgradeable proxy
|
||||
* @param name of the contract
|
||||
* @param version representing the first version to be set for the proxy
|
||||
* @return address of the new proxy created
|
||||
*/
|
||||
function createProxy(string name, uint version) public payable returns (UpgradeabilityProxy) {
|
||||
bytes32 key = keccak256(name);
|
||||
require(proxies[key] == 0x0);
|
||||
UpgradeabilityProxy proxy = new UpgradeabilityProxy(name, version);
|
||||
proxies[key] = address(proxy);
|
||||
Upgradeable(proxy).initialize.value(msg.value)(msg.sender);
|
||||
ProxyCreated(name, proxy);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
import './Proxy.sol';
|
||||
import './IRegistry.sol';
|
||||
import './UpgradeabilityStorage.sol';
|
||||
|
||||
/**
|
||||
* @title UpgradeabilityProxy
|
||||
* @dev This contract represents a proxy where the implementation address to which it will delegate can be upgraded
|
||||
*/
|
||||
contract UpgradeabilityProxy is Proxy, UpgradeabilityStorage {
|
||||
|
||||
function UpgradeabilityProxy(string _name, uint _version) public {
|
||||
_proxiedContractName = _name;
|
||||
registry = IRegistry(msg.sender);
|
||||
upgradeTo(_version);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Upgrades the implementation to the requested version
|
||||
* @param _version representing the version name of the new implementation to be set
|
||||
*/
|
||||
function upgradeTo(uint _version) public {
|
||||
require(msg.sender == address(registry));
|
||||
_implementation = registry.getVersion(_proxiedContractName, _version);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
import './IRegistry.sol';
|
||||
|
||||
/**
|
||||
* @title UpgradeabilityStorage
|
||||
* @dev This contract holds all the necessary state variables to support the upgrade functionality
|
||||
*/
|
||||
contract UpgradeabilityStorage {
|
||||
// Versions registry
|
||||
IRegistry internal registry;
|
||||
|
||||
// Address of the current implementation
|
||||
address internal _implementation;
|
||||
|
||||
// contract name
|
||||
string public _proxiedContractName;
|
||||
|
||||
|
||||
modifier requireRegistry() {
|
||||
require(address(registry) != 0x0);
|
||||
_;
|
||||
}
|
||||
modifier onlyRegistryContractFor(string name) {
|
||||
require(address(registry) != 0x0);
|
||||
require(msg.sender == registry.getProxyFor(name));
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Tells the address of the current implementation
|
||||
* @return address of the current implementation
|
||||
*/
|
||||
function implementation() public view returns (address) {
|
||||
return _implementation;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
import './UpgradeabilityStorage.sol';
|
||||
|
||||
/**
|
||||
* @title Upgradeable
|
||||
* @dev This contract holds all the minimum required functionality for a behavior to be upgradeable.
|
||||
* This means, required state variables for owned upgradeability purpose and simple initialization validation.
|
||||
*/
|
||||
contract Upgradeable is UpgradeabilityStorage {
|
||||
/**
|
||||
* @dev Validates the caller is the versions registry.
|
||||
* THIS FUNCTION SHOULD BE OVERRIDDEN CALLING SUPER
|
||||
* @param sender representing the address deploying the initial behavior of the contract
|
||||
*/
|
||||
function initialize(address sender) public payable {
|
||||
require(msg.sender == address(registry));
|
||||
}
|
||||
}
|
||||
53
deployments/rinkeby/contribution.md
Normal file
53
deployments/rinkeby/contribution.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Contribution deployments
|
||||
|
||||
aragon apm publish major --environment=rinkeby"
|
||||
|
||||
## 2019-04-24 update balances
|
||||
|
||||
✔ Successfully published kredits-contribution.open.aragonpm.eth v6.0.0:
|
||||
ℹ Contract address: 0x2c083EEA83fd3a99C93759D97D0317A43261c758
|
||||
ℹ Content (ipfs): QmULpSqz7BgTFmDu8AL7YZZEz525xkcEzf3dPKtbRdUtFs
|
||||
ℹ Transaction hash: 0x8b01c4c00162e918659d267a2beaf33b578e2aaf9f427f1aa9a43029333c5cd7
|
||||
|
||||
## 2019-04-10 - Weltempfänger release
|
||||
|
||||
✔ Successfully published kredits-contribution.open.aragonpm.eth v5.0.0:
|
||||
ℹ Contract address: 0xe0f7dB486321b917e3A986Bdb2F2b9d51BA98fa9
|
||||
ℹ Content (ipfs): QmU3XEBb4f5jU8MFFEpwaa95C1mhc82UeYLRWLrKsvcQNw
|
||||
ℹ Transaction hash: 0xd736ff5f79f8142be3fad1a50580fb40aa468838da397f8630285fd91a445af3
|
||||
|
||||
|
||||
## 2019-04-04
|
||||
|
||||
✔ Successfully published kredits-contribution.open.aragonpm.eth v4.0.0:
|
||||
ℹ Contract address: 0x7485e8fbde0112C53587079db450Eb002D359372
|
||||
ℹ Content (ipfs): QmZKxYPm8wz4phgL4428Gh7MjmbyFFDMP2st7qhNL9qGDQ
|
||||
ℹ Transaction hash: 0x7d9be7920db675be88e8f60ebf08dc62ee77c4e6e454c5fbf0f91f6ac97e4c26
|
||||
|
||||
|
||||
## 2019-03-26
|
||||
|
||||
### v3.0.0 appids
|
||||
from account: 0x18f6d06de7e6d556b1bbb5875f8cfafb5eaef9c5
|
||||
✔ Successfully published kredits-contribution.open.aragonpm.eth v3.0.0:
|
||||
ℹ Contract address: 0x9b4954834f070380faf9B6CB3794C7eA92d3B506
|
||||
ℹ Content (ipfs): Qma3yvT5AmBbJHL8WkpXHs7aCFqpGd9ZaMpbiz3cT6Un59
|
||||
ℹ Transaction hash: 0xc2b2d19e1b6d68ba50ed051a35c22eac74c69bd50665aed65488f9209171d382
|
||||
|
||||
## 2019-03-25
|
||||
|
||||
### v2.0.0 updated appid hashes
|
||||
from account: 0x18f6d06de7e6d556b1bbb5875f8cfafb5eaef9c5
|
||||
✔ Successfully published kredits-contribution.open.aragonpm.eth v2.0.0:
|
||||
ℹ Contract address: 0x2765F13d82B83C0C9d770715e1fB376ab01C0361
|
||||
ℹ Content (ipfs): QmYiv1cMh6cj8pcbmaTUAWxf93k4UhN8mPJWeqEo7BEkMx
|
||||
ℹ Transaction hash: 0xe4841a6552527c8fbeb6aa44769f95ce60d99413958c6289f67e8ec83823ee96
|
||||
|
||||
|
||||
### v1.0.0
|
||||
from account: 0x18f6d06de7e6d556b1bbb5875f8cfafb5eaef9c5
|
||||
✔ Successfully published kredits-contribution.open.aragonpm.eth v1.0.0:
|
||||
ℹ Contract address: 0x1F460107361047064d982f61002D1BdEb02Ce705
|
||||
ℹ Content (ipfs): QmQ6rTWCGcseCmGb6thYG2kwijHk6W84qaFPeftZ4bUY2k
|
||||
ℹ Transaction hash: 0xeee90c5d18a8cb8ac845f52a4202cd62b27c23b4251b69c3681a854786b6e336
|
||||
|
||||
51
deployments/rinkeby/contributor.md
Normal file
51
deployments/rinkeby/contributor.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Contributor deployments
|
||||
|
||||
aragon apm publish major --environment=rinkeby
|
||||
|
||||
## 2019-04-25 canPerform fix
|
||||
|
||||
✔ Successfully published kredits-contributor.open.aragonpm.eth v6.0.0:
|
||||
ℹ Contract address: 0xA5379D49C718845A1BD7720c6BE3872bA69906cc
|
||||
ℹ Content (ipfs): QmdennNV6s2FNpe6QNYxrUsUXPVdnQGvh1vCi22Tqs8ojq
|
||||
ℹ Transaction hash: 0x51077afeff70a24e87c78bb23ea13bdb9b4445bd43ea7a74a4178fadfeeb6c35
|
||||
|
||||
## 2019-04-24 update balances
|
||||
|
||||
✔ Successfully published kredits-contributor.open.aragonpm.eth v5.0.0:
|
||||
ℹ Contract address: 0xadefa3b66b68a127Fe38bEa1813b844EE69CFD86
|
||||
ℹ Content (ipfs): QmeygbQgoj2McLWzo9hJayLWuBZqFaK4HTpa5qLeQdkn5K
|
||||
ℹ Transaction hash: 0x4237a9636f6e4a8190e0d5bcfa85a452da097bf654a173a88e0e1de3d078f08d
|
||||
|
||||
|
||||
## 2019-04-10 - Weltempfänger release
|
||||
|
||||
✔ Successfully published kredits-contributor.open.aragonpm.eth v4.0.0:
|
||||
ℹ Contract address: 0x08a6D4D915FCAA5524F05F5F715a6C17cB6eeA6B
|
||||
ℹ Content (ipfs): QmR62PWwe1EzommfkhJDYcTvHoZjbXuv9dTG6vCn5dWCsb
|
||||
ℹ Transaction hash: 0xd5317c9e207a413485c55ec3046b09d467d978443680304737a6d7d3db0c90e1
|
||||
|
||||
|
||||
## 2019-04-04
|
||||
|
||||
✔ Successfully published kredits-contributor.open.aragonpm.eth v3.0.0:
|
||||
ℹ Contract address: 0x95D8458E28C8de7216279512601A3B9Dc512D70B
|
||||
ℹ Content (ipfs): QmSpHnmsf8FybvqfD49kwxvDixwiBUR7D5yG4BWSnnwCPS
|
||||
ℹ Transaction hash: 0x736f9751b07a91178f453c279ecb57604b3b5686ae5d7115880f3b27fbeb50f2
|
||||
|
||||
## 2019-03-26
|
||||
|
||||
### v2.0.0 support for appids
|
||||
from account: 0x18f6d06de7e6d556b1bbb5875f8cfafb5eaef9c5
|
||||
✔ Successfully published kredits-contributor.open.aragonpm.eth v2.0.0:
|
||||
ℹ Contract address: 0xf8e7B45b3c5A98dbE3D69C6828052dfD9fe2dc69
|
||||
ℹ Content (ipfs): QmTDduMJVUVcqz5SgVEns1xwY9LqYrMoAyYcx3pMrPxn6i
|
||||
ℹ Transaction hash: 0x48b38f32f5dcb52a0a8603743b66a7ca490fec04ccb1888dcfd37106bbd3b886
|
||||
|
||||
|
||||
## 2019-03-25
|
||||
from account: 0x18f6d06de7e6d556b1bbb5875f8cfafb5eaef9c5
|
||||
✔ Successfully published kredits-contributor.open.aragonpm.eth v1.0.0:
|
||||
ℹ Contract address: 0x6D80EFEE6F9A40AA86Ef7c4C95c8b2e453d260fb
|
||||
ℹ Content (ipfs): QmbGSQPwi3AXHjDFG2fkMpJrBJLtyuaA6DVPMkFTfMpksn
|
||||
ℹ Transaction hash: 0x26376c59dfdb617c35b740a0f110bf3040cdad0103593cdc788267a84d9847b9
|
||||
|
||||
57
deployments/rinkeby/dao.md
Normal file
57
deployments/rinkeby/dao.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Kredits deployment
|
||||
|
||||
## 2019-04-25 canPerfom fix
|
||||
|
||||
aragon dao upgrade 0xc34edf7d11b7f8433d597f0bb0697acdff55ef14 kredits-contributor.open.aragonpm.eth --environment=rinkeby
|
||||
✔ Fetching kredits-contributor.open.aragonpm.eth@latest
|
||||
✔ Upgrading app
|
||||
✔ Successfully executed: "Set the resolving address of 'kredits-contributor.open.aragonpm.eth' in namespace 'App code' to 0xA5379D49C718845A1BD7720c6BE3872bA69906cc"
|
||||
|
||||
## 2019-04-24 upgrade contributor and contribution
|
||||
|
||||
aragon dao upgrade 0xc34edf7d11b7f8433d597f0bb0697acdff55ef14 kredits-contributor.open.aragonpm.eth --environment=rinkeby
|
||||
eth-provider | Invalid provider preset/location: "local"
|
||||
✔ Fetching kredits-contributor.open.aragonpm.eth@latest
|
||||
✔ Upgrading app
|
||||
✔ Successfully executed: "Set the resolving address of 'kredits-contributor.open.aragonpm.eth' in namespace 'App code' to 0xadefa3b66b68a127Fe38bEa1813b844EE69CFD86"
|
||||
|
||||
aragon dao upgrade 0xc34edf7d11b7f8433d597f0bb0697acdff55ef14 kredits-contribution.open.aragonpm.eth --environment=rinkeby
|
||||
✔ Fetching kredits-contribution.open.aragonpm.eth@latest
|
||||
✔ Upgrading app
|
||||
✔ Successfully executed: "Set the resolving address of 'kredits-contribution.open.aragonpm.eth' in namespace 'App code' to 0x2c083EEA83fd3a99C93759D97D0317A43261c758"
|
||||
|
||||
## 2019-04-10 - Weltempfänger release
|
||||
|
||||
Using KreditsKit at: 0x76e069b47b79442657eaf0555a32c6b16fa1b8b4
|
||||
Created new DAO at: 0xc34edf7d11b7f8433d597f0bb0697acdff55ef14
|
||||
|
||||
## 2019-04-04
|
||||
|
||||
Using KreditsKit at: 0x76e069b47b79442657eaf0555a32c6b16fa1b8b4
|
||||
Created new DAO at: 0xcd75458fbc4aa2231252d5b21f1391fd031e5cb2
|
||||
|
||||
### 2019-03-26
|
||||
|
||||
kredits/truffle-kredits@aragonos » truffle exec scripts/new-dao.js --network=rinkeby
|
||||
Using network 'rinkeby'.
|
||||
|
||||
Deploying to networkId: 4
|
||||
Using KreditsKit at: 0x1d6a9c2146a330575ee860eef9a012b5ff7caa68
|
||||
|
||||
Created new DAO at: 0x95a7ce185efc2d1f13efd2a00ee9247c51ea7009"
|
||||
|
||||
|
||||
### 2019-03-25
|
||||
|
||||
kredits/truffle-kredits@aragonos » aragon contracts exec scripts/new-dao.js --network=rinkeby
|
||||
ℹ Use of `--network` is deprecated and has been replaced with `--environment`. You may need to update your arapp.json
|
||||
ℹ Passing the command to Truffle
|
||||
Using network 'rinkeby'.
|
||||
|
||||
Deploying to networkId: 4
|
||||
Using KreditsKit at: 0xf4f3963718e5c2b426dd5c3ef0ab4b31ffb7a318
|
||||
|
||||
Created new DAO at: 0x8b7c0bec9476ce08d9769a87d272b03b350712e2
|
||||
|
||||
from account: 0x18f6d06de7e6d556b1bbb5875f8cfafb5eaef9c5
|
||||
https://rinkeby.etherscan.io/tx/0x4deb02b3740b3baa7735097d57c1456a5cb329ee741d123478fdb5114e2c305b
|
||||
62
deployments/rinkeby/kreditskit.md
Normal file
62
deployments/rinkeby/kreditskit.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# KreditsKit deployments
|
||||
|
||||
## 2019-04-04
|
||||
|
||||
Deploying to networkId: 4
|
||||
Using ENS at: 0x98Df287B6C145399Aaa709692c8D308357bC085D
|
||||
Using DAOFactory at: 0x2298d27a9b847c681d2b2c2828ab9d79013f5f1d
|
||||
Found apps: [contribution,contributor,proposal,token].open.aragonpm.eth
|
||||
Deployed KreditsKit at: 0x76e069b47b79442657eaf0555a32c6b16fa1b8b4
|
||||
|
||||
## 2019-03-26
|
||||
|
||||
Using network 'rinkeby'.
|
||||
|
||||
Deploying to networkId: 4
|
||||
Using ENS at: 0x98Df287B6C145399Aaa709692c8D308357bC085D
|
||||
Using DAOFactory at: 0x2298d27a9b847c681d2b2c2828ab9d79013f5f1d
|
||||
Found apps: [contribution,contributor,proposal,token].open.aragonpm.eth
|
||||
Deployed KreditsKit at: 0x1d6a9c2146a330575ee860eef9a012b5ff7caa68
|
||||
|
||||
|
||||
|
||||
### fails
|
||||
a few deployments to fix the deploy script
|
||||
|
||||
## 2019-03-25
|
||||
|
||||
### fixed kit with correct appids
|
||||
|
||||
kredits/truffle-kredits@aragonos » aragon contracts exec scripts/deploy-kit.js --debug --network=rinkeby
|
||||
ℹ Use of `--network` is deprecated and has been replaced with `--environment`. You may need to update your arapp.json
|
||||
ℹ Passing the command to Truffle
|
||||
Using network 'rinkeby'.
|
||||
|
||||
Deploying to networkId: 4
|
||||
Using ENS at: 0x98Df287B6C145399Aaa709692c8D308357bC085D
|
||||
Using DAOFactory at: 0x2298d27a9b847c681d2b2c2828ab9d79013f5f1d
|
||||
Found apps: [contribution,contributor,proposal,token].open.aragonpm.eth
|
||||
Deployed KreditsKit at: 0xf4f3963718e5c2b426dd5c3ef0ab4b31ffb7a318
|
||||
|
||||
from account: 0x18f6d06de7e6d556b1bbb5875f8cfafb5eaef9c5
|
||||
|
||||
### test with fixed deploy script
|
||||
kredits/truffle-kredits@aragonos » ENS=0x98df287b6c145399aaa709692c8d308357bc085d DAO_FACTORY=0x2298d27a9b847c681d2b2c2828ab9d79013f5f1d truffle exec scripts/deploy-kit.js --network=rinkeby
|
||||
Using network 'rinkeby'.
|
||||
|
||||
Deploying to networkId: 4
|
||||
Using ENS at: 0x98df287b6c145399aaa709692c8d308357bc085d
|
||||
Using DAOFactory at: 0x2298d27a9b847c681d2b2c2828ab9d79013f5f1d
|
||||
Deployed KreditsKit at: 0x83afd3c99563fc467aec69e0187ffd53fc8faa76
|
||||
|
||||
### success
|
||||
kredits/truffle-kredits@aragonos » ENS=0x98df287b6c145399aaa709692c8d308357bc085d DAO_FACTORY=0x2298d27a9b847c681d2b2c2828ab9d79013f5f1d truffle exec scripts/deploy-kit.js --network=rinkeby
|
||||
Using network 'rinkeby'.
|
||||
|
||||
Using ENS at: 0x98df287b6c145399aaa709692c8d308357bc085d
|
||||
Using DAOFactory at: 0x2298d27a9b847c681d2b2c2828ab9d79013f5f1d
|
||||
Deployed KreditsKit at: 0x1fd2f9206addaf86f3ef921a3b7c84400374ba68
|
||||
|
||||
### deployment script error:
|
||||
deployment script failure at: https://rinkeby.etherscan.io/tx/0x3571b889b6b9b2b3f26dd0ee7fb82c7ece90b28d910078f2e06753d878832af4"
|
||||
|
||||
43
deployments/rinkeby/proposal.md
Normal file
43
deployments/rinkeby/proposal.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Proposal deployments
|
||||
|
||||
## 2019-04-10 - Weltempfänger release
|
||||
|
||||
✔ Successfully published kredits-proposal.open.aragonpm.eth v5.0.0:
|
||||
ℹ Contract address: 0x4ce5b0286483c66b861e5599a199054687434552
|
||||
ℹ Content (ipfs): QmNYXEcmvKTGxYiob7WUf85oZhdmFDCuGiA6TsRrDE9TYb
|
||||
ℹ Transaction hash: 0x0482b58a1ba87d494c6391026399d0ac41b45384330d916f3f99ba70e501584b
|
||||
|
||||
|
||||
## 2019-04-04
|
||||
|
||||
✔ Successfully published kredits-proposal.open.aragonpm.eth v4.0.0:
|
||||
ℹ Contract address: 0x4993275362Ba50D76f349A262B7b842e7FbD7490
|
||||
ℹ Content (ipfs): QmesCPKLapASPTB3rnPpSdD7ULkg8BQwRcpdE1B8WwfSh7
|
||||
ℹ Transaction hash: 0xe4be7b1a75b663eb345b957b216a8476b0f75e2bbfc5880943b05c82fab15dff
|
||||
|
||||
|
||||
## 2019-03-26
|
||||
|
||||
### v3.0.0 appids
|
||||
from account: 0x18f6d06de7e6d556b1bbb5875f8cfafb5eaef9c5
|
||||
✔ Successfully published kredits-proposal.open.aragonpm.eth v3.0.0:
|
||||
ℹ Contract address: 0x9f47c31aBB6F53ff2fec09C0bF79c3337C20f5AA
|
||||
ℹ Content (ipfs): Qmdxg33FxAQSH7U8oTApaM5SgUUC9btiA6tu5Hystzp5tV
|
||||
ℹ Transaction hash: 0xceb572f3fff368b9f07fc835577529a113e2de8ff7972a51ffaf4c63acbda9eb
|
||||
|
||||
|
||||
## 2019-03-25
|
||||
|
||||
### v2.0.0 updated appid hashes
|
||||
from account: 0x18f6d06de7e6d556b1bbb5875f8cfafb5eaef9c5
|
||||
✔ Successfully published kredits-proposal.open.aragonpm.eth v2.0.0:
|
||||
ℹ Contract address: 0x0a48dc5415f4d7A3B2B4a9aaD4A7a8775f923ce3
|
||||
ℹ Content (ipfs): QmZej9xPJN7aTiQ7SzWziRuzEjjfMzjPakcGYcoN8QQBMH
|
||||
ℹ Transaction hash: 0xf14c308b9f92b43a719fab2602c624dc2e11d0f629a0be9a6ec8ac47719ee9ca
|
||||
|
||||
### v1.0.0
|
||||
from account: 0x18f6d06de7e6d556b1bbb5875f8cfafb5eaef9c5
|
||||
✔ Successfully published kredits-proposal.open.aragonpm.eth v1.0.0:
|
||||
ℹ Contract address: 0xFc04eB3eF666507F96A22d330d8a852d8eC996EA
|
||||
ℹ Content (ipfs): QmRTzoYr7B5f8gDGY8RmoodJkMm59D4jSJLZNRnhAd4wCg
|
||||
ℹ Transaction hash: 0xce419d9d555551eefc624a7ac87c19b5d660eb9c4fe0da611cd5e28e3ee6844f
|
||||
34
deployments/rinkeby/token.md
Normal file
34
deployments/rinkeby/token.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Token deployments
|
||||
|
||||
## 2019-04-10 - Weltempfänger release
|
||||
|
||||
✔ Successfully published kredits-token.open.aragonpm.eth v4.0.0:
|
||||
ℹ Contract address: 0x05E0C2bbdA8e5BeE22AC1E20C1457dA4de63aE26
|
||||
ℹ Content (ipfs): QmUuYLRMRNZcundUk2pxVaSjMNvtB7hzdf3eyoaUNqDPow
|
||||
ℹ Transaction hash: 0x98c28b5ca645904d56eb83c4783682f018c0fcee015b3a3d5fa8bd609223fb89
|
||||
|
||||
|
||||
## 2019-04-04
|
||||
|
||||
✔ Successfully published kredits-token.open.aragonpm.eth v3.0.0:
|
||||
ℹ Contract address: 0xd9913A96e087f50E71BF14c62cBCa3b9635392A9
|
||||
ℹ Content (ipfs): QmfZ7LwjkQRuLsEnVjrEF3ryTaHsL6YTxffiiDS5KWmHQG
|
||||
ℹ Transaction hash: 0x102b27e154d1e144ec084f5e8dc78e1626fda9f26c20db3e3b230fac381c317a
|
||||
|
||||
|
||||
## 2019-03-26
|
||||
|
||||
### v2.0.0 support for appIds
|
||||
from account: 0x18f6d06de7e6d556b1bbb5875f8cfafb5eaef9c5
|
||||
✔ Successfully published kredits-token.open.aragonpm.eth v2.0.0:
|
||||
ℹ Contract address: 0xc126919B3b30F14b848c2cc66Ec21A1e85a7c621
|
||||
ℹ Content (ipfs): QmWB9JrWa93vtdv5VG2yohiWTbDiuzbz9P58apJdP3FnNP
|
||||
ℹ Transaction hash: 0xa5ccd532a91d67b0616ee5505144988be4360440daf70dc2f5108dd2a59f3d68
|
||||
|
||||
|
||||
## 2019-03-25
|
||||
from account: 0x18f6d06de7e6d556b1bbb5875f8cfafb5eaef9c5
|
||||
✔ Successfully published kredits-token.open.aragonpm.eth v1.0.0:
|
||||
ℹ Contract address: 0xB4147Be6d4bcC790c6CbD3d508354DDfd3EbC8e6
|
||||
ℹ Content (ipfs): QmQPue7WzQhaXbTLJwyZXSHaRY1u5ezWxyVmBP8bEgGoTE
|
||||
ℹ Transaction hash: 0xa7866d81e236adfeaff6bf2d5dbc9f9757fbc1b0ce689357901194913fe93a3b"
|
||||
BIN
docs/kredits-diagram.png
Normal file
BIN
docs/kredits-diagram.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
1
lib/abis/ACL.json
Normal file
1
lib/abis/ACL.json
Normal file
File diff suppressed because one or more lines are too long
1
lib/abis/Contribution.json
Normal file
1
lib/abis/Contribution.json
Normal file
File diff suppressed because one or more lines are too long
1
lib/abis/Contributor.json
Normal file
1
lib/abis/Contributor.json
Normal file
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"contributors","outputs":[{"name":"account","type":"address"},{"name":"ipfsHash","type":"bytes32"},{"name":"hashFunction","type":"uint8"},{"name":"hashSize","type":"uint8"},{"name":"isCore","type":"bool"},{"name":"exists","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"implementation","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_proxiedContractName","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"contributorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"contributorIds","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"oldIpfsHash","type":"bytes32"},{"indexed":false,"name":"newIpfsHash","type":"bytes32"}],"name":"ContributorProfileUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"oldAccount","type":"address"},{"indexed":false,"name":"newAccount","type":"address"}],"name":"ContributorAccountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"account","type":"address"}],"name":"ContributorAdded","type":"event"},{"constant":false,"inputs":[{"name":"sender","type":"address"}],"name":"initialize","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"coreContributorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"},{"name":"oldAccount","type":"address"},{"name":"newAccount","type":"address"}],"name":"updateContributorAccount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"},{"name":"ipfsHash","type":"bytes32"},{"name":"hashFunction","type":"uint8"},{"name":"hashSize","type":"uint8"}],"name":"updateContributorIpfsHash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"},{"name":"ipfsHash","type":"bytes32"},{"name":"hashFunction","type":"uint8"},{"name":"hashSize","type":"uint8"},{"name":"isCore","type":"bool"}],"name":"addContributor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"}],"name":"isCore","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"}],"name":"exists","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"addressIsCore","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"addressExists","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"getContributorIdByAddress","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"}],"name":"getContributorAddressById","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"}],"name":"getContributorById","outputs":[{"name":"id","type":"uint256"},{"name":"account","type":"address"},{"name":"ipfsHash","type":"bytes32"},{"name":"hashFunction","type":"uint8"},{"name":"hashSize","type":"uint8"},{"name":"isCore","type":"bool"},{"name":"balance","type":"uint256"},{"name":"exists","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}]
|
||||
1
lib/abis/Kernel.json
Normal file
1
lib/abis/Kernel.json
Normal file
File diff suppressed because one or more lines are too long
1
lib/abis/KreditsKit.json
Normal file
1
lib/abis/KreditsKit.json
Normal file
@@ -0,0 +1 @@
|
||||
[{"constant":true,"inputs":[],"name":"ens","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"fac","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"appId","type":"bytes32"}],"name":"latestVersionAppBase","outputs":[{"name":"base","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"appIds","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_fac","type":"address"},{"name":"_ens","type":"address"},{"name":"_appIds","type":"bytes32[4]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"dao","type":"address"}],"name":"DeployInstance","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"dao","type":"address"},{"indexed":false,"name":"appProxy","type":"address"},{"indexed":false,"name":"appId","type":"bytes32"}],"name":"InstalledApp","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"appProxy","type":"address"},{"indexed":false,"name":"appId","type":"bytes32"}],"name":"InstalledApp","type":"event"},{"constant":false,"inputs":[],"name":"newInstance","outputs":[{"name":"dao","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]
|
||||
@@ -1 +0,0 @@
|
||||
[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"proposals","outputs":[{"name":"creatorAccount","type":"address"},{"name":"contributorId","type":"uint256"},{"name":"votesCount","type":"uint256"},{"name":"votesNeeded","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"executed","type":"bool"},{"name":"ipfsHash","type":"bytes32"},{"name":"hashFunction","type":"uint8"},{"name":"hashSize","type":"uint8"},{"name":"exists","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"proposalsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"implementation","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_proxiedContractName","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"sender","type":"address"}],"name":"initialize","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"creatorAccount","type":"address"},{"indexed":false,"name":"contributorId","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"ProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"voterId","type":"uint256"},{"indexed":false,"name":"totalVotes","type":"uint256"}],"name":"ProposalVoted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"contributorId","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"ProposalExecuted","type":"event"},{"constant":true,"inputs":[],"name":"contributorsContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"contributorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"coreContributorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"contributorId","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"ipfsHash","type":"bytes32"},{"name":"hashFunction","type":"uint8"},{"name":"hashSize","type":"uint8"}],"name":"addProposal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"proposalId","type":"uint256"}],"name":"getProposal","outputs":[{"name":"id","type":"uint256"},{"name":"creatorAccount","type":"address"},{"name":"contributorId","type":"uint256"},{"name":"votesCount","type":"uint256"},{"name":"votesNeeded","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"executed","type":"bool"},{"name":"ipfsHash","type":"bytes32"},{"name":"hashFunction","type":"uint8"},{"name":"hashSize","type":"uint8"},{"name":"voterIds","type":"uint256[]"},{"name":"exists","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"proposalId","type":"uint256"}],"name":"vote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
|
||||
1
lib/abis/Proposal.json
Normal file
1
lib/abis/Proposal.json
Normal file
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
[{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"currentVersions","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"proxies","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"uint256"}],"name":"versions","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"name","type":"string"},{"indexed":false,"name":"proxy","type":"address"}],"name":"ProxyCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"name","type":"string"},{"indexed":false,"name":"version","type":"uint256"},{"indexed":false,"name":"implementation","type":"address"}],"name":"VersionAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"name","type":"string"},{"indexed":false,"name":"version","type":"uint256"}],"name":"ProxyImplementationUpgraded","type":"event"},{"constant":false,"inputs":[{"name":"name","type":"string"},{"name":"implementation","type":"address"}],"name":"addVersion","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"name","type":"string"},{"name":"version","type":"uint256"}],"name":"getVersion","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"name","type":"string"}],"name":"getLatestVersion","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"name","type":"string"}],"name":"getProxyFor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"name","type":"string"},{"name":"version","type":"uint256"}],"name":"upgrade","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"name","type":"string"}],"name":"upgradeToLatest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"name","type":"string"},{"name":"version","type":"uint256"}],"name":"createProxy","outputs":[{"name":"","type":"address"}],"payable":true,"stateMutability":"payable","type":"function"}]
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
{"42":"0x205fe1b3dac678b594c5f0535e7d158e38591f93","100":"0xa7fc9b1f678c41396b53904f94f50a42ff44d826"}
|
||||
3
lib/addresses/KreditsKit.json
Normal file
3
lib/addresses/KreditsKit.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"4": "0x76e069b47b79442657eaf0555a32c6b16fa1b8b4"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
{"42":"0x9fd66ee78a5ebe86006f12b37ff59c63f9caa15b","100":"0x95d3bd7d136bb0b7ac9988097e964236f8a9976e"}
|
||||
@@ -1 +0,0 @@
|
||||
{"42":"0xc270e6ea4fe303df9f1a3d4a132ac425264082e7","100":"0x7458dea485d9d8301e3ce43e8a1ec1456be5ba83"}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user