refactor contrats with aragonos
This commit is contained in:
		
							parent
							
								
									d687ff604e
								
							
						
					
					
						commit
						6c569239de
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,4 +1,6 @@
 | 
			
		||||
build
 | 
			
		||||
flattened_contracts
 | 
			
		||||
node_modules
 | 
			
		||||
**/node_modules
 | 
			
		||||
.ganache-db
 | 
			
		||||
.tm_properties
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
							
								
								
									
										162
									
								
								apps/contribution/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								apps/contribution/README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,162 @@
 | 
			
		||||
# Aragon React Boilerplate
 | 
			
		||||
 | 
			
		||||
> 🕵️ [Find more boilerplates using GitHub](https://github.com/search?q=topic:aragon-boilerplate) | 
 | 
			
		||||
> ✨ [Official boilerplates](https://github.com/search?q=topic:aragon-boilerplate+org:aragon)
 | 
			
		||||
 | 
			
		||||
React boilerplate for Aragon applications.
 | 
			
		||||
 | 
			
		||||
This boilerplate also includes a fully working example app, complete with a background worker and a front-end in React (with Aragon UI).
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
```sh
 | 
			
		||||
aragon init app.aragonpm.eth react
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Running your app
 | 
			
		||||
 | 
			
		||||
### Using HTTP
 | 
			
		||||
 | 
			
		||||
Running your app using HTTP will allow for a faster development process of your app's front-end, as it can be hot-reloaded without the need to execute `aragon run` every time a change is made.
 | 
			
		||||
 | 
			
		||||
- First start your app's development server running `npm run start:app`, and keep that process running. By default it will rebuild the app and reload the server when changes to the source are made.
 | 
			
		||||
 | 
			
		||||
- After that, you can run `npm run start:aragon:http` which will compile your app's contracts, publish the app locally and create a DAO. You will need to stop it and run it again after making changes to your smart contracts.
 | 
			
		||||
 | 
			
		||||
Changes to the app's background script (`app/script.js`) cannot be hot-reloaded, after making changes to the script, you will need to either restart the development server (`npm run start:app`) or rebuild the script `npm run build:script`.
 | 
			
		||||
 | 
			
		||||
### Using IPFS
 | 
			
		||||
 | 
			
		||||
Running your app using IPFS will mimic the production environment that will be used for running your app. `npm run start:aragon:ipfs` will run your app using IPFS. Whenever a change is made to any file in your front-end, a new version of the app needs to be published, so the command needs to be restarted.
 | 
			
		||||
 | 
			
		||||
## What's in the box?
 | 
			
		||||
 | 
			
		||||
### npm Scripts
 | 
			
		||||
 | 
			
		||||
- **start** or **start:aragon:ipfs**: Runs your app inside a DAO served from IPFS
 | 
			
		||||
- **start:aragon:http**: Runs your app inside a DAO served with HTTP (hot reloading)
 | 
			
		||||
- **start:app**: Starts a development server for your app
 | 
			
		||||
- **compile**: Compile the smart contracts
 | 
			
		||||
- **build**: Builds the front-end and background script
 | 
			
		||||
- **build:app**: Builds the front-end
 | 
			
		||||
- **build:script**: Builds the background script
 | 
			
		||||
- **test**: Runs tests for the contracts
 | 
			
		||||
- **publish:patch**: Release a patch version to aragonPM (only frontend/content changes allowed)
 | 
			
		||||
- **publish:minor**: Release a minor version to aragonPM (only frontend/content changes allowed)
 | 
			
		||||
- **publish:major**: Release a major version to aragonPM (frontend **and** contract changes)
 | 
			
		||||
- **versions**: Check the currently installed versions of the app
 | 
			
		||||
 | 
			
		||||
### Libraries
 | 
			
		||||
 | 
			
		||||
- [**@aragon/os**](https://github.com/aragon/aragonos): Aragon interfaces
 | 
			
		||||
- [**@aragon/client**](https://github.com/aragon/aragon.js/tree/master/packages/aragon-client): Wrapper for Aragon application RPC
 | 
			
		||||
- [**@aragon/ui**](https://github.com/aragon/aragon-ui): Aragon UI components (in React)
 | 
			
		||||
 | 
			
		||||
## Publish
 | 
			
		||||
 | 
			
		||||
This app has 3 environments defined in `arapp.json`:
 | 
			
		||||
 | 
			
		||||
| Environment   | Network   |
 | 
			
		||||
|---            |---        |
 | 
			
		||||
| default       | localhost |
 | 
			
		||||
| staging       | rinkeby   |
 | 
			
		||||
| production    | mainnet   |
 | 
			
		||||
 | 
			
		||||
Prerequisites:
 | 
			
		||||
- ENS Registry address
 | 
			
		||||
 | 
			
		||||
Note: the `default` environment which points to `localhost` does not have an ENS Registry address specified because the `@aragon/cli` will default the value to `0xB9462EF3441346dBc6E49236Edbb0dF207db09B7` (the ENS Registry pre-deployed on the local development chain).
 | 
			
		||||
 | 
			
		||||
### Introduction to environments
 | 
			
		||||
 | 
			
		||||
Environments are defined in `arapp.json`, for example `staging` points to:
 | 
			
		||||
- an ENS registry (`0x314159265dd8dbb310642f98f50c066173c1259b`)
 | 
			
		||||
- an APM registry (`open.aragonpm.eth`)
 | 
			
		||||
- an APM repository (`app`)
 | 
			
		||||
- an Ethereum network (`rinkeby`)
 | 
			
		||||
- an Ethereum websockets provider (`wss://rinkeby.eth.aragon.network/ws` - to **read** from the blockchain)
 | 
			
		||||
 | 
			
		||||
The `rinkeby` network is further defined in `truffle.js`, and has:
 | 
			
		||||
- an Ethereum provider (to **write** to the blockchain):
 | 
			
		||||
    - an address (`https://rinkeby.infura.io`)
 | 
			
		||||
    - an Ethereum Account (`0xb4124cEB3451635DAcedd11767f004d8a28c6eE7`)
 | 
			
		||||
    (which is the first account generated from the `DEFAULT_MNEMONIC` variable, to use a different account see [here](#Using-a-different-Ethereum-account))
 | 
			
		||||
 | 
			
		||||
### Major version: content + contract
 | 
			
		||||
 | 
			
		||||
Command:
 | 
			
		||||
```
 | 
			
		||||
npm run publish:major -- --environment staging
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This will:
 | 
			
		||||
1. _build_ the app's frontend (the output lives in `dist`)
 | 
			
		||||
2. _compile_ the app's contract (the output lives in `build`)
 | 
			
		||||
3. publish the app to the **staging** environment.
 | 
			
		||||
 | 
			
		||||
Sample output:
 | 
			
		||||
```
 | 
			
		||||
 > aragon apm publish major "--environment" "staging"
 | 
			
		||||
 | 
			
		||||
 ✔ Successfully published app.open.aragonpm.eth v1.0.0: 
 | 
			
		||||
 ℹ Contract address: 0xE636bcA5B95e94F749F63E322a04DB59362299F1
 | 
			
		||||
 ℹ Content (ipfs): QmR695Wu5KrHNec7pRP3kPvwYihABDAyVYdX5D5vwLgxCn
 | 
			
		||||
 ℹ Transaction hash: 0x3d752db29cc106e9ff98b260a90615921eb32471425a29ead8cbb830fb224d8
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Note: the contract location is defined in `arapp.json` under `path`.
 | 
			
		||||
Note: you can also deploy a major version with only frontend changes by passing `--only-content`.
 | 
			
		||||
 | 
			
		||||
### Minor/patch version: content only
 | 
			
		||||
 | 
			
		||||
Command:
 | 
			
		||||
```
 | 
			
		||||
npm run publish:patch -- --environment staging
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This will:
 | 
			
		||||
1. _build_ the app's frontend (which lives in `dist`)
 | 
			
		||||
2. publish the app to the **staging** environment.
 | 
			
		||||
 | 
			
		||||
Sample output:
 | 
			
		||||
```
 | 
			
		||||
 ✔ Successfully published app.open.aragonpm.eth v1.1.1: 
 | 
			
		||||
 ℹ Contract address: 0xE636bcA5B95e94F749F63E322a04DB59362299F1
 | 
			
		||||
 ℹ Content (ipfs): QmUYv9cjyNVxCyAJGK2YXjkbzh6u4iW2ak81Z9obdefM1q
 | 
			
		||||
 ℹ Transaction hash: 0x57864d8efd8d439008621b494b19a3e8f876a8a46b38475f9626802f0a1403c2
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Check published versions
 | 
			
		||||
 | 
			
		||||
Command:
 | 
			
		||||
```
 | 
			
		||||
npm run versions -- --environment staging
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Sample output:
 | 
			
		||||
```
 | 
			
		||||
 ℹ app.open.aragonpm.eth has 4 published versions
 | 
			
		||||
 ✔ 1.0.0: 0xE636bcA5B95e94F749F63E322a04DB59362299F1 ipfs:QmR695Wu5KrHNec7pRP3kPvwYihABDAyVYdX5D5vwLgxCn
 | 
			
		||||
 ✔ 1.1.0: 0xE636bcA5B95e94F749F63E322a04DB59362299F1 ipfs:QmSwjUZFpv2c2e9fLoxtgFrAsAmBN4DyQGJp4RcqQcW3z3
 | 
			
		||||
 ✔ 1.1.1: 0xE636bcA5B95e94F749F63E322a04DB59362299F1 ipfs:QmUYv9cjyNVxCyAJGK2YXjkbzh6u4iW2ak81Z9obdefM1q
 | 
			
		||||
 ✔ 2.0.0: 0x74CBbbC932d7C344FCd789Eba24BfD40e52980c9 ipfs:Qmadb3hzwLDKtb93fF367Vg1epkdsLZF4dhpapNYynjgZF
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Using a different Ethereum account
 | 
			
		||||
 | 
			
		||||
To deploy from a different account, you can:
 | 
			
		||||
- define a `~/.aragon/mnemonic.json` file
 | 
			
		||||
    ```
 | 
			
		||||
    {
 | 
			
		||||
        "mnemonic": "explain tackle mirror kit ..."
 | 
			
		||||
    }
 | 
			
		||||
    ```
 | 
			
		||||
    or
 | 
			
		||||
- define a `~/.aragon/${network_name}_key.json` file, for example: `~/.aragon/rinkeby_key.json`
 | 
			
		||||
    ```
 | 
			
		||||
    {
 | 
			
		||||
        "keys": [
 | 
			
		||||
            "a8a54b2d8197bc0b19bb8a084031be71835580a01e70a45a13babd16c9bc1563"
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
    ```
 | 
			
		||||
							
								
								
									
										33
									
								
								apps/contribution/arapp.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								apps/contribution/arapp.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
{
 | 
			
		||||
  "roles": [
 | 
			
		||||
    {
 | 
			
		||||
      "name": "Add contributions",
 | 
			
		||||
      "id": "ADD_CONTRIBUTION_ROLE",
 | 
			
		||||
      "params": []
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "Manage token contract",
 | 
			
		||||
      "id": "MANAGE_TOKEN_CONTRACT_ROLE",
 | 
			
		||||
      "params": []
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "environments": {
 | 
			
		||||
    "default": {
 | 
			
		||||
      "network": "development",
 | 
			
		||||
      "appName": "contribution.aragonpm.eth"
 | 
			
		||||
    },
 | 
			
		||||
    "staging": {
 | 
			
		||||
      "registry": "0x98df287b6c145399aaa709692c8d308357bc085d",
 | 
			
		||||
      "appName": "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"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										139
									
								
								apps/contribution/contracts/Contribution.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								apps/contribution/contracts/Contribution.sol
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,139 @@
 | 
			
		||||
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, uint256 proposalId) external;
 | 
			
		||||
  function mintFor(address contributorAccount, uint256 amount, uint256 contributionId) public;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
contract Contribution is AragonApp {
 | 
			
		||||
  bytes32 public constant ADD_CONTRIBUTION_ROLE = keccak256("ADD_CONTRIBUTION_ROLE");
 | 
			
		||||
 | 
			
		||||
  bytes32 public constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb;
 | 
			
		||||
  bytes32 public constant TOKEN_APP_ID = 0xe04a882e7a6adf5603207d545ea49aec17e6b936c4d9eae3d74dbe482264991a;
 | 
			
		||||
 | 
			
		||||
  struct ContributionData {
 | 
			
		||||
    address contributor;
 | 
			
		||||
    uint256 amount;
 | 
			
		||||
    bool claimed;
 | 
			
		||||
    bytes32 hashDigest;
 | 
			
		||||
    uint8 hashFunction;
 | 
			
		||||
    uint8 hashSize;
 | 
			
		||||
    string tokenMetadataURL;
 | 
			
		||||
    uint claimAfterBlock;
 | 
			
		||||
    bool exists;
 | 
			
		||||
  }
 | 
			
		||||
  string internal name_;
 | 
			
		||||
  string internal symbol_;
 | 
			
		||||
 | 
			
		||||
  address public tokenContract;
 | 
			
		||||
 | 
			
		||||
  mapping(uint256 => address) contributionOwner;
 | 
			
		||||
  mapping(address => uint256[]) ownedContributions;
 | 
			
		||||
 | 
			
		||||
  mapping(uint256 => ContributionData) public contributions;
 | 
			
		||||
  uint256 public contributionsCount;
 | 
			
		||||
 | 
			
		||||
  uint256 public blocksToWait = 0;
 | 
			
		||||
 | 
			
		||||
  event ContributionAdded(uint256 id, address indexed contributor, uint256 amount);
 | 
			
		||||
  event ContributionClaimed(uint256 id, address indexed contributor, uint256 amount);
 | 
			
		||||
 | 
			
		||||
  function initialize() public onlyInit {
 | 
			
		||||
    initialized();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function name() external view returns (string) {
 | 
			
		||||
    return name_;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function symbol() external view returns (string) {
 | 
			
		||||
    return symbol_;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function balanceOf(address owner) public view returns (uint256) {
 | 
			
		||||
    require(owner != address(0));
 | 
			
		||||
    return ownedContributions[owner].length;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function ownerOf(uint256 contributionId) public view returns (address) {
 | 
			
		||||
    require(exists(contributionId));
 | 
			
		||||
    return contributions[contributionId].contributor;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function tokenOfOwnerByIndex(address contributor, uint256 index) public view returns (uint256) {
 | 
			
		||||
    return ownedContributions[contributor][index];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function tokenMetadata(uint256 contributionId) public view returns (string) {
 | 
			
		||||
    return contributions[contributionId].tokenMetadataURL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function getContribution(uint256 contributionId) public view returns (uint256 id, address contributor, uint256 amount, bool claimed, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint claimAfterBlock, bool exists) {
 | 
			
		||||
    id = contributionId;
 | 
			
		||||
    ContributionData storage c = contributions[id];
 | 
			
		||||
    return (
 | 
			
		||||
      id,
 | 
			
		||||
      c.contributor,
 | 
			
		||||
      c.amount, 
 | 
			
		||||
      c.claimed, 
 | 
			
		||||
      c.hashDigest,
 | 
			
		||||
      c.hashFunction,
 | 
			
		||||
      c.hashSize,
 | 
			
		||||
      c.claimAfterBlock,
 | 
			
		||||
      c.exists
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function add(uint256 amount, address contributorAccount, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(ADD_CONTRIBUTION_ROLE) {
 | 
			
		||||
    //require(canPerform(msg.sender, ADD_CONTRIBUTION_ROLE, new uint256[](0)), 'nope');
 | 
			
		||||
    uint256 contributionId = contributionsCount + 1;
 | 
			
		||||
    ContributionData storage c = contributions[contributionId];
 | 
			
		||||
    c.exists = true;
 | 
			
		||||
    c.amount = amount;
 | 
			
		||||
    c.claimed = false;
 | 
			
		||||
    c.contributor = contributorAccount;
 | 
			
		||||
    c.hashDigest = hashDigest;
 | 
			
		||||
    c.hashFunction = hashFunction;
 | 
			
		||||
    c.hashSize = hashSize;
 | 
			
		||||
    c.claimAfterBlock = block.number; // + blocksToWait;
 | 
			
		||||
 | 
			
		||||
    contributionsCount++;
 | 
			
		||||
 | 
			
		||||
    contributionOwner[contributionId] = contributorAccount;
 | 
			
		||||
    ownedContributions[contributorAccount].push(contributionId);
 | 
			
		||||
 
 | 
			
		||||
    emit ContributionAdded(contributionId, contributorAccount, amount);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function claim(uint256 contributionId) public isInitialized {
 | 
			
		||||
    ContributionData storage c = contributions[contributionId];
 | 
			
		||||
    require(c.exists, 'NOT_FOUND');
 | 
			
		||||
    require(!c.claimed, 'ALREADY_CLAIMED');
 | 
			
		||||
    require(block.number > c.claimAfterBlock, 'NOT_CLAIMABLE');
 | 
			
		||||
    //c.claimed = true;
 | 
			
		||||
    //IToken(getTokenContract()).mintFor(c.contributor, c.amount, contributionId); // somehow this does not work
 | 
			
		||||
    bytes4 sig = bytes4(keccak256("mintFor()"));
 | 
			
		||||
    address token = getTokenContract();
 | 
			
		||||
    //IToken token = IToken(getTokenContract());
 | 
			
		||||
 | 
			
		||||
    //token.call(sig);
 | 
			
		||||
    //IToken(token).mintFor(c.contributor, c.amount, contributionId);
 | 
			
		||||
    IToken(token).mintFor(c.contributor, c.amount, contributionId);
 | 
			
		||||
    
 | 
			
		||||
    //emit ContributionClaimed(contributionId, c.contributor, c.amount);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function getTokenContract() public view returns (address) {
 | 
			
		||||
    return 0x8779fc70eeea01d00efa9044c29d3c930fdb874a;
 | 
			
		||||
    //IKernel k = IKernel(kernel());
 | 
			
		||||
 | 
			
		||||
    //return k.getApp(KERNEL_APP_ADDR_NAMESPACE, TOKEN_APP_ID);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  function exists(uint256 contributionId) view public returns (bool) {
 | 
			
		||||
    return contributions[contributionId].exists;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
pragma solidity ^0.4.17;
 | 
			
		||||
pragma solidity ^0.4.4;
 | 
			
		||||
 | 
			
		||||
contract Migrations {
 | 
			
		||||
  address public owner;
 | 
			
		||||
@ -8,15 +8,15 @@ contract Migrations {
 | 
			
		||||
    if (msg.sender == owner) _;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function Migrations() public {
 | 
			
		||||
  function Migrations() {
 | 
			
		||||
    owner = msg.sender;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function setCompleted(uint completed) public restricted {
 | 
			
		||||
  function setCompleted(uint completed) restricted {
 | 
			
		||||
    last_completed_migration = completed;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function upgrade(address new_address) public restricted {
 | 
			
		||||
  function upgrade(address new_address) restricted {
 | 
			
		||||
    Migrations upgraded = Migrations(new_address);
 | 
			
		||||
    upgraded.setCompleted(last_completed_migration);
 | 
			
		||||
  }
 | 
			
		||||
							
								
								
									
										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)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21093
									
								
								apps/contribution/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										21093
									
								
								apps/contribution/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										28
									
								
								apps/contribution/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								apps/contribution/package.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "app-name",
 | 
			
		||||
  "version": "1.0.0",
 | 
			
		||||
  "description": "",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@aragon/os": "^4.1.0",
 | 
			
		||||
    "@aragon/cli": "^5.5.0"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
  },
 | 
			
		||||
  "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": "npm run sync-assets && npm run build:script -- --no-minify && parcel serve app/index.html -p 8001 --out-dir dist/ --no-cache",
 | 
			
		||||
    "test": "aragon contracts test",
 | 
			
		||||
    "compile": "aragon contracts compile",
 | 
			
		||||
    "sync-assets": "copy-aragon-ui-assets -n aragon-ui ./dist",
 | 
			
		||||
    "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"
 | 
			
		||||
  },
 | 
			
		||||
  "keywords": []
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								apps/contribution/test/app.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								apps/contribution/test/app.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
const CounterApp = artifacts.require('Contribution.sol')
 | 
			
		||||
 | 
			
		||||
contract('Contribution', (accounts) => {
 | 
			
		||||
  it('should be tested')
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										63
									
								
								apps/contribution/truffle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								apps/contribution/truffle.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
			
		||||
/**
 | 
			
		||||
 * https://github.com/aragon/aragonOS/blob/v4.0.0/truffle-config.js
 | 
			
		||||
 */
 | 
			
		||||
const homedir = require('homedir')
 | 
			
		||||
const path = require('path')
 | 
			
		||||
 | 
			
		||||
const HDWalletProvider = require('truffle-hdwallet-provider')
 | 
			
		||||
const HDWalletProviderPrivkey = require('truffle-hdwallet-provider-privkey')
 | 
			
		||||
 | 
			
		||||
const DEFAULT_MNEMONIC = 'explain tackle mirror kit van hammer degree position ginger unfair soup bonus'
 | 
			
		||||
 | 
			
		||||
const defaultRPC = (network) =>
 | 
			
		||||
  `https://${network}.infura.io`
 | 
			
		||||
 | 
			
		||||
const configFilePath = (filename) =>
 | 
			
		||||
  path.join(homedir(), `.aragon/${filename}`)
 | 
			
		||||
 | 
			
		||||
const mnemonic = () => {
 | 
			
		||||
  try {
 | 
			
		||||
    return require(configFilePath('mnemonic.json')).mnemonic
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    return DEFAULT_MNEMONIC
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const settingsForNetwork = (network) => {
 | 
			
		||||
  try {
 | 
			
		||||
    return require(configFilePath(`${network}_key.json`))
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    return { }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Lazily loaded provider
 | 
			
		||||
const providerForNetwork = (network) => (
 | 
			
		||||
  () => {
 | 
			
		||||
    let { rpc, keys } = settingsForNetwork(network)
 | 
			
		||||
    rpc = rpc || defaultRPC(network)
 | 
			
		||||
 | 
			
		||||
    if (!keys || keys.length == 0) {
 | 
			
		||||
      return new HDWalletProvider(mnemonic(), rpc)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return new HDWalletProviderPrivkey(keys, rpc)
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
module.exports = {
 | 
			
		||||
  networks: {
 | 
			
		||||
    development: {
 | 
			
		||||
      host: 'localhost',
 | 
			
		||||
      port: 8545,
 | 
			
		||||
      network_id: '*'
 | 
			
		||||
    },
 | 
			
		||||
    mainnet: {
 | 
			
		||||
      network_id: 1,
 | 
			
		||||
      provider: providerForNetwork('mainnet')
 | 
			
		||||
    },
 | 
			
		||||
    rinkeby: {
 | 
			
		||||
      network_id: 4,
 | 
			
		||||
      provider: providerForNetwork('rinkeby')
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
							
								
								
									
										162
									
								
								apps/contributor/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								apps/contributor/README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,162 @@
 | 
			
		||||
# Aragon React Boilerplate
 | 
			
		||||
 | 
			
		||||
> 🕵️ [Find more boilerplates using GitHub](https://github.com/search?q=topic:aragon-boilerplate) | 
 | 
			
		||||
> ✨ [Official boilerplates](https://github.com/search?q=topic:aragon-boilerplate+org:aragon)
 | 
			
		||||
 | 
			
		||||
React boilerplate for Aragon applications.
 | 
			
		||||
 | 
			
		||||
This boilerplate also includes a fully working example app, complete with a background worker and a front-end in React (with Aragon UI).
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
```sh
 | 
			
		||||
aragon init app.aragonpm.eth react
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Running your app
 | 
			
		||||
 | 
			
		||||
### Using HTTP
 | 
			
		||||
 | 
			
		||||
Running your app using HTTP will allow for a faster development process of your app's front-end, as it can be hot-reloaded without the need to execute `aragon run` every time a change is made.
 | 
			
		||||
 | 
			
		||||
- First start your app's development server running `npm run start:app`, and keep that process running. By default it will rebuild the app and reload the server when changes to the source are made.
 | 
			
		||||
 | 
			
		||||
- After that, you can run `npm run start:aragon:http` which will compile your app's contracts, publish the app locally and create a DAO. You will need to stop it and run it again after making changes to your smart contracts.
 | 
			
		||||
 | 
			
		||||
Changes to the app's background script (`app/script.js`) cannot be hot-reloaded, after making changes to the script, you will need to either restart the development server (`npm run start:app`) or rebuild the script `npm run build:script`.
 | 
			
		||||
 | 
			
		||||
### Using IPFS
 | 
			
		||||
 | 
			
		||||
Running your app using IPFS will mimic the production environment that will be used for running your app. `npm run start:aragon:ipfs` will run your app using IPFS. Whenever a change is made to any file in your front-end, a new version of the app needs to be published, so the command needs to be restarted.
 | 
			
		||||
 | 
			
		||||
## What's in the box?
 | 
			
		||||
 | 
			
		||||
### npm Scripts
 | 
			
		||||
 | 
			
		||||
- **start** or **start:aragon:ipfs**: Runs your app inside a DAO served from IPFS
 | 
			
		||||
- **start:aragon:http**: Runs your app inside a DAO served with HTTP (hot reloading)
 | 
			
		||||
- **start:app**: Starts a development server for your app
 | 
			
		||||
- **compile**: Compile the smart contracts
 | 
			
		||||
- **build**: Builds the front-end and background script
 | 
			
		||||
- **build:app**: Builds the front-end
 | 
			
		||||
- **build:script**: Builds the background script
 | 
			
		||||
- **test**: Runs tests for the contracts
 | 
			
		||||
- **publish:patch**: Release a patch version to aragonPM (only frontend/content changes allowed)
 | 
			
		||||
- **publish:minor**: Release a minor version to aragonPM (only frontend/content changes allowed)
 | 
			
		||||
- **publish:major**: Release a major version to aragonPM (frontend **and** contract changes)
 | 
			
		||||
- **versions**: Check the currently installed versions of the app
 | 
			
		||||
 | 
			
		||||
### Libraries
 | 
			
		||||
 | 
			
		||||
- [**@aragon/os**](https://github.com/aragon/aragonos): Aragon interfaces
 | 
			
		||||
- [**@aragon/client**](https://github.com/aragon/aragon.js/tree/master/packages/aragon-client): Wrapper for Aragon application RPC
 | 
			
		||||
- [**@aragon/ui**](https://github.com/aragon/aragon-ui): Aragon UI components (in React)
 | 
			
		||||
 | 
			
		||||
## Publish
 | 
			
		||||
 | 
			
		||||
This app has 3 environments defined in `arapp.json`:
 | 
			
		||||
 | 
			
		||||
| Environment   | Network   |
 | 
			
		||||
|---            |---        |
 | 
			
		||||
| default       | localhost |
 | 
			
		||||
| staging       | rinkeby   |
 | 
			
		||||
| production    | mainnet   |
 | 
			
		||||
 | 
			
		||||
Prerequisites:
 | 
			
		||||
- ENS Registry address
 | 
			
		||||
 | 
			
		||||
Note: the `default` environment which points to `localhost` does not have an ENS Registry address specified because the `@aragon/cli` will default the value to `0xB9462EF3441346dBc6E49236Edbb0dF207db09B7` (the ENS Registry pre-deployed on the local development chain).
 | 
			
		||||
 | 
			
		||||
### Introduction to environments
 | 
			
		||||
 | 
			
		||||
Environments are defined in `arapp.json`, for example `staging` points to:
 | 
			
		||||
- an ENS registry (`0x314159265dd8dbb310642f98f50c066173c1259b`)
 | 
			
		||||
- an APM registry (`open.aragonpm.eth`)
 | 
			
		||||
- an APM repository (`app`)
 | 
			
		||||
- an Ethereum network (`rinkeby`)
 | 
			
		||||
- an Ethereum websockets provider (`wss://rinkeby.eth.aragon.network/ws` - to **read** from the blockchain)
 | 
			
		||||
 | 
			
		||||
The `rinkeby` network is further defined in `truffle.js`, and has:
 | 
			
		||||
- an Ethereum provider (to **write** to the blockchain):
 | 
			
		||||
    - an address (`https://rinkeby.infura.io`)
 | 
			
		||||
    - an Ethereum Account (`0xb4124cEB3451635DAcedd11767f004d8a28c6eE7`)
 | 
			
		||||
    (which is the first account generated from the `DEFAULT_MNEMONIC` variable, to use a different account see [here](#Using-a-different-Ethereum-account))
 | 
			
		||||
 | 
			
		||||
### Major version: content + contract
 | 
			
		||||
 | 
			
		||||
Command:
 | 
			
		||||
```
 | 
			
		||||
npm run publish:major -- --environment staging
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This will:
 | 
			
		||||
1. _build_ the app's frontend (the output lives in `dist`)
 | 
			
		||||
2. _compile_ the app's contract (the output lives in `build`)
 | 
			
		||||
3. publish the app to the **staging** environment.
 | 
			
		||||
 | 
			
		||||
Sample output:
 | 
			
		||||
```
 | 
			
		||||
 > aragon apm publish major "--environment" "staging"
 | 
			
		||||
 | 
			
		||||
 ✔ Successfully published app.open.aragonpm.eth v1.0.0: 
 | 
			
		||||
 ℹ Contract address: 0xE636bcA5B95e94F749F63E322a04DB59362299F1
 | 
			
		||||
 ℹ Content (ipfs): QmR695Wu5KrHNec7pRP3kPvwYihABDAyVYdX5D5vwLgxCn
 | 
			
		||||
 ℹ Transaction hash: 0x3d752db29cc106e9ff98b260a90615921eb32471425a29ead8cbb830fb224d8
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Note: the contract location is defined in `arapp.json` under `path`.
 | 
			
		||||
Note: you can also deploy a major version with only frontend changes by passing `--only-content`.
 | 
			
		||||
 | 
			
		||||
### Minor/patch version: content only
 | 
			
		||||
 | 
			
		||||
Command:
 | 
			
		||||
```
 | 
			
		||||
npm run publish:patch -- --environment staging
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This will:
 | 
			
		||||
1. _build_ the app's frontend (which lives in `dist`)
 | 
			
		||||
2. publish the app to the **staging** environment.
 | 
			
		||||
 | 
			
		||||
Sample output:
 | 
			
		||||
```
 | 
			
		||||
 ✔ Successfully published app.open.aragonpm.eth v1.1.1: 
 | 
			
		||||
 ℹ Contract address: 0xE636bcA5B95e94F749F63E322a04DB59362299F1
 | 
			
		||||
 ℹ Content (ipfs): QmUYv9cjyNVxCyAJGK2YXjkbzh6u4iW2ak81Z9obdefM1q
 | 
			
		||||
 ℹ Transaction hash: 0x57864d8efd8d439008621b494b19a3e8f876a8a46b38475f9626802f0a1403c2
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Check published versions
 | 
			
		||||
 | 
			
		||||
Command:
 | 
			
		||||
```
 | 
			
		||||
npm run versions -- --environment staging
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Sample output:
 | 
			
		||||
```
 | 
			
		||||
 ℹ app.open.aragonpm.eth has 4 published versions
 | 
			
		||||
 ✔ 1.0.0: 0xE636bcA5B95e94F749F63E322a04DB59362299F1 ipfs:QmR695Wu5KrHNec7pRP3kPvwYihABDAyVYdX5D5vwLgxCn
 | 
			
		||||
 ✔ 1.1.0: 0xE636bcA5B95e94F749F63E322a04DB59362299F1 ipfs:QmSwjUZFpv2c2e9fLoxtgFrAsAmBN4DyQGJp4RcqQcW3z3
 | 
			
		||||
 ✔ 1.1.1: 0xE636bcA5B95e94F749F63E322a04DB59362299F1 ipfs:QmUYv9cjyNVxCyAJGK2YXjkbzh6u4iW2ak81Z9obdefM1q
 | 
			
		||||
 ✔ 2.0.0: 0x74CBbbC932d7C344FCd789Eba24BfD40e52980c9 ipfs:Qmadb3hzwLDKtb93fF367Vg1epkdsLZF4dhpapNYynjgZF
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Using a different Ethereum account
 | 
			
		||||
 | 
			
		||||
To deploy from a different account, you can:
 | 
			
		||||
- define a `~/.aragon/mnemonic.json` file
 | 
			
		||||
    ```
 | 
			
		||||
    {
 | 
			
		||||
        "mnemonic": "explain tackle mirror kit ..."
 | 
			
		||||
    }
 | 
			
		||||
    ```
 | 
			
		||||
    or
 | 
			
		||||
- define a `~/.aragon/${network_name}_key.json` file, for example: `~/.aragon/rinkeby_key.json`
 | 
			
		||||
    ```
 | 
			
		||||
    {
 | 
			
		||||
        "keys": [
 | 
			
		||||
            "a8a54b2d8197bc0b19bb8a084031be71835580a01e70a45a13babd16c9bc1563"
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
    ```
 | 
			
		||||
							
								
								
									
										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": "contributor.aragonpm.eth"
 | 
			
		||||
    },
 | 
			
		||||
    "staging": {
 | 
			
		||||
      "registry": "0x98df287b6c145399aaa709692c8d308357bc085d",
 | 
			
		||||
      "appName": "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"
 | 
			
		||||
}
 | 
			
		||||
@ -1,10 +1,9 @@
 | 
			
		||||
pragma solidity ^0.4.18;
 | 
			
		||||
pragma solidity ^0.4.24;
 | 
			
		||||
 | 
			
		||||
// import basic ERC20 details to be able to call balanceOf
 | 
			
		||||
import 'zeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol';
 | 
			
		||||
import './upgradeable/Upgradeable.sol';
 | 
			
		||||
import "@aragon/os/contracts/apps/AragonApp.sol";
 | 
			
		||||
 | 
			
		||||
contract Contributors is Upgradeable {
 | 
			
		||||
contract Contributor is AragonApp {
 | 
			
		||||
  bytes32 public constant MANAGE_CONTRIBUTORS_ROLE = keccak256("MANAGE_CONTRIBUTORS_ROLE");
 | 
			
		||||
 | 
			
		||||
  struct Contributor {
 | 
			
		||||
    address account;
 | 
			
		||||
@ -23,20 +22,16 @@ contract Contributors is Upgradeable {
 | 
			
		||||
  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;
 | 
			
		||||
  function initialize(address root) public onlyInit {
 | 
			
		||||
    uint _id = contributorsCount + 1;
 | 
			
		||||
    Contributor storage c = contributors[_id];
 | 
			
		||||
    c.exists = true;
 | 
			
		||||
    c.isCore = true;
 | 
			
		||||
    c.account = sender;
 | 
			
		||||
    contributorIds[sender] = _id;
 | 
			
		||||
    c.account = root;
 | 
			
		||||
    contributorIds[root] = _id;
 | 
			
		||||
    contributorsCount += 1;
 | 
			
		||||
 | 
			
		||||
    initialized();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function coreContributorsCount() view public returns (uint) {
 | 
			
		||||
@ -49,14 +44,14 @@ contract Contributors is Upgradeable {
 | 
			
		||||
    return count;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function updateContributorAccount(uint id, address oldAccount, address newAccount) public onlyCoreOrOperator {
 | 
			
		||||
  function updateContributorAccount(uint 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 updateContributorIpfsHash(uint id, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize) public onlyCoreOrOperator {
 | 
			
		||||
  function updateContributorIpfsHash(uint id, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize) public isInitialized auth(MANAGE_CONTRIBUTORS_ROLE) {
 | 
			
		||||
    Contributor storage c = contributors[id];
 | 
			
		||||
    bytes32 oldIpfsHash = c.ipfsHash;
 | 
			
		||||
    c.ipfsHash = ipfsHash;
 | 
			
		||||
@ -66,7 +61,7 @@ contract Contributors is Upgradeable {
 | 
			
		||||
    ContributorProfileUpdated(id, oldIpfsHash, c.ipfsHash);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function addContributor(address account, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize, bool isCore) public onlyCoreOrOperator {
 | 
			
		||||
  function addContributor(address account, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize, bool isCore) public isInitialized auth(MANAGE_CONTRIBUTORS_ROLE) {
 | 
			
		||||
    require(!addressExists(account));
 | 
			
		||||
    uint _id = contributorsCount + 1;
 | 
			
		||||
    assert(!contributors[_id].exists); // this can not be acually
 | 
			
		||||
@ -80,7 +75,7 @@ contract Contributors is Upgradeable {
 | 
			
		||||
    contributorIds[account] = _id;
 | 
			
		||||
 | 
			
		||||
    contributorsCount += 1;
 | 
			
		||||
    ContributorAdded(_id, account);
 | 
			
		||||
    emit ContributorAdded(_id, account);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function isCore(uint id) view public returns (bool) {
 | 
			
		||||
@ -112,7 +107,7 @@ contract Contributors is Upgradeable {
 | 
			
		||||
    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 ) {
 | 
			
		||||
  function getContributorById(uint _id) public view returns (uint id, address account, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize, bool isCore, bool exists ) {
 | 
			
		||||
    id = _id;
 | 
			
		||||
    Contributor storage c = contributors[_id];
 | 
			
		||||
    account = c.account;
 | 
			
		||||
@ -121,8 +116,9 @@ contract Contributors is Upgradeable {
 | 
			
		||||
    hashSize = c.hashSize;
 | 
			
		||||
    isCore = c.isCore;
 | 
			
		||||
    exists = c.exists;
 | 
			
		||||
    
 | 
			
		||||
    ERC20Basic token = ERC20Basic(registry.getProxyFor('Token'));
 | 
			
		||||
    balance = token.balanceOf(account);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function canPerform(address _who, address _where, bytes32 _what, uint256[] _how) public view returns (bool) {
 | 
			
		||||
    return addressExists(_who);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								apps/contributor/contracts/misc/Migrations.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								apps/contributor/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 Migrations() {
 | 
			
		||||
    owner = msg.sender;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function setCompleted(uint completed) restricted {
 | 
			
		||||
    last_completed_migration = completed;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function upgrade(address new_address) restricted {
 | 
			
		||||
    Migrations upgraded = Migrations(new_address);
 | 
			
		||||
    upgraded.setCompleted(last_completed_migration);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										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)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13527
									
								
								apps/contributor/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										13527
									
								
								apps/contributor/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										27
									
								
								apps/contributor/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								apps/contributor/package.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "kredits-contributor",
 | 
			
		||||
  "version": "1.0.0",
 | 
			
		||||
  "description": "",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@aragon/os": "^4.1.0",
 | 
			
		||||
    "@aragon/cli": "^5.5.0"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {},
 | 
			
		||||
  "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": "",
 | 
			
		||||
    "test": "aragon contracts test",
 | 
			
		||||
    "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"
 | 
			
		||||
  },
 | 
			
		||||
  "keywords": []
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								apps/contributor/test/app.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								apps/contributor/test/app.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
const CounterApp = artifacts.require('CounterApp.sol')
 | 
			
		||||
 | 
			
		||||
contract('CounterApp', (accounts) => {
 | 
			
		||||
  it('should be tested')
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										63
									
								
								apps/contributor/truffle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								apps/contributor/truffle.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
			
		||||
/**
 | 
			
		||||
 * https://github.com/aragon/aragonOS/blob/v4.0.0/truffle-config.js
 | 
			
		||||
 */
 | 
			
		||||
const homedir = require('homedir')
 | 
			
		||||
const path = require('path')
 | 
			
		||||
 | 
			
		||||
const HDWalletProvider = require('truffle-hdwallet-provider')
 | 
			
		||||
const HDWalletProviderPrivkey = require('truffle-hdwallet-provider-privkey')
 | 
			
		||||
 | 
			
		||||
const DEFAULT_MNEMONIC = 'explain tackle mirror kit van hammer degree position ginger unfair soup bonus'
 | 
			
		||||
 | 
			
		||||
const defaultRPC = (network) =>
 | 
			
		||||
  `https://${network}.infura.io`
 | 
			
		||||
 | 
			
		||||
const configFilePath = (filename) =>
 | 
			
		||||
  path.join(homedir(), `.aragon/${filename}`)
 | 
			
		||||
 | 
			
		||||
const mnemonic = () => {
 | 
			
		||||
  try {
 | 
			
		||||
    return require(configFilePath('mnemonic.json')).mnemonic
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    return DEFAULT_MNEMONIC
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const settingsForNetwork = (network) => {
 | 
			
		||||
  try {
 | 
			
		||||
    return require(configFilePath(`${network}_key.json`))
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    return { }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Lazily loaded provider
 | 
			
		||||
const providerForNetwork = (network) => (
 | 
			
		||||
  () => {
 | 
			
		||||
    let { rpc, keys } = settingsForNetwork(network)
 | 
			
		||||
    rpc = rpc || defaultRPC(network)
 | 
			
		||||
 | 
			
		||||
    if (!keys || keys.length == 0) {
 | 
			
		||||
      return new HDWalletProvider(mnemonic(), rpc)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return new HDWalletProviderPrivkey(keys, rpc)
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
module.exports = {
 | 
			
		||||
  networks: {
 | 
			
		||||
    development: {
 | 
			
		||||
      host: 'localhost',
 | 
			
		||||
      port: 8545,
 | 
			
		||||
      network_id: '*'
 | 
			
		||||
    },
 | 
			
		||||
    mainnet: {
 | 
			
		||||
      network_id: 1,
 | 
			
		||||
      provider: providerForNetwork('mainnet')
 | 
			
		||||
    },
 | 
			
		||||
    rinkeby: {
 | 
			
		||||
      network_id: 4,
 | 
			
		||||
      provider: providerForNetwork('rinkeby')
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										162
									
								
								apps/proposal/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								apps/proposal/README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,162 @@
 | 
			
		||||
# Aragon React Boilerplate
 | 
			
		||||
 | 
			
		||||
> 🕵️ [Find more boilerplates using GitHub](https://github.com/search?q=topic:aragon-boilerplate) | 
 | 
			
		||||
> ✨ [Official boilerplates](https://github.com/search?q=topic:aragon-boilerplate+org:aragon)
 | 
			
		||||
 | 
			
		||||
React boilerplate for Aragon applications.
 | 
			
		||||
 | 
			
		||||
This boilerplate also includes a fully working example app, complete with a background worker and a front-end in React (with Aragon UI).
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
```sh
 | 
			
		||||
aragon init app.aragonpm.eth react
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Running your app
 | 
			
		||||
 | 
			
		||||
### Using HTTP
 | 
			
		||||
 | 
			
		||||
Running your app using HTTP will allow for a faster development process of your app's front-end, as it can be hot-reloaded without the need to execute `aragon run` every time a change is made.
 | 
			
		||||
 | 
			
		||||
- First start your app's development server running `npm run start:app`, and keep that process running. By default it will rebuild the app and reload the server when changes to the source are made.
 | 
			
		||||
 | 
			
		||||
- After that, you can run `npm run start:aragon:http` which will compile your app's contracts, publish the app locally and create a DAO. You will need to stop it and run it again after making changes to your smart contracts.
 | 
			
		||||
 | 
			
		||||
Changes to the app's background script (`app/script.js`) cannot be hot-reloaded, after making changes to the script, you will need to either restart the development server (`npm run start:app`) or rebuild the script `npm run build:script`.
 | 
			
		||||
 | 
			
		||||
### Using IPFS
 | 
			
		||||
 | 
			
		||||
Running your app using IPFS will mimic the production environment that will be used for running your app. `npm run start:aragon:ipfs` will run your app using IPFS. Whenever a change is made to any file in your front-end, a new version of the app needs to be published, so the command needs to be restarted.
 | 
			
		||||
 | 
			
		||||
## What's in the box?
 | 
			
		||||
 | 
			
		||||
### npm Scripts
 | 
			
		||||
 | 
			
		||||
- **start** or **start:aragon:ipfs**: Runs your app inside a DAO served from IPFS
 | 
			
		||||
- **start:aragon:http**: Runs your app inside a DAO served with HTTP (hot reloading)
 | 
			
		||||
- **start:app**: Starts a development server for your app
 | 
			
		||||
- **compile**: Compile the smart contracts
 | 
			
		||||
- **build**: Builds the front-end and background script
 | 
			
		||||
- **build:app**: Builds the front-end
 | 
			
		||||
- **build:script**: Builds the background script
 | 
			
		||||
- **test**: Runs tests for the contracts
 | 
			
		||||
- **publish:patch**: Release a patch version to aragonPM (only frontend/content changes allowed)
 | 
			
		||||
- **publish:minor**: Release a minor version to aragonPM (only frontend/content changes allowed)
 | 
			
		||||
- **publish:major**: Release a major version to aragonPM (frontend **and** contract changes)
 | 
			
		||||
- **versions**: Check the currently installed versions of the app
 | 
			
		||||
 | 
			
		||||
### Libraries
 | 
			
		||||
 | 
			
		||||
- [**@aragon/os**](https://github.com/aragon/aragonos): Aragon interfaces
 | 
			
		||||
- [**@aragon/client**](https://github.com/aragon/aragon.js/tree/master/packages/aragon-client): Wrapper for Aragon application RPC
 | 
			
		||||
- [**@aragon/ui**](https://github.com/aragon/aragon-ui): Aragon UI components (in React)
 | 
			
		||||
 | 
			
		||||
## Publish
 | 
			
		||||
 | 
			
		||||
This app has 3 environments defined in `arapp.json`:
 | 
			
		||||
 | 
			
		||||
| Environment   | Network   |
 | 
			
		||||
|---            |---        |
 | 
			
		||||
| default       | localhost |
 | 
			
		||||
| staging       | rinkeby   |
 | 
			
		||||
| production    | mainnet   |
 | 
			
		||||
 | 
			
		||||
Prerequisites:
 | 
			
		||||
- ENS Registry address
 | 
			
		||||
 | 
			
		||||
Note: the `default` environment which points to `localhost` does not have an ENS Registry address specified because the `@aragon/cli` will default the value to `0xB9462EF3441346dBc6E49236Edbb0dF207db09B7` (the ENS Registry pre-deployed on the local development chain).
 | 
			
		||||
 | 
			
		||||
### Introduction to environments
 | 
			
		||||
 | 
			
		||||
Environments are defined in `arapp.json`, for example `staging` points to:
 | 
			
		||||
- an ENS registry (`0x314159265dd8dbb310642f98f50c066173c1259b`)
 | 
			
		||||
- an APM registry (`open.aragonpm.eth`)
 | 
			
		||||
- an APM repository (`app`)
 | 
			
		||||
- an Ethereum network (`rinkeby`)
 | 
			
		||||
- an Ethereum websockets provider (`wss://rinkeby.eth.aragon.network/ws` - to **read** from the blockchain)
 | 
			
		||||
 | 
			
		||||
The `rinkeby` network is further defined in `truffle.js`, and has:
 | 
			
		||||
- an Ethereum provider (to **write** to the blockchain):
 | 
			
		||||
    - an address (`https://rinkeby.infura.io`)
 | 
			
		||||
    - an Ethereum Account (`0xb4124cEB3451635DAcedd11767f004d8a28c6eE7`)
 | 
			
		||||
    (which is the first account generated from the `DEFAULT_MNEMONIC` variable, to use a different account see [here](#Using-a-different-Ethereum-account))
 | 
			
		||||
 | 
			
		||||
### Major version: content + contract
 | 
			
		||||
 | 
			
		||||
Command:
 | 
			
		||||
```
 | 
			
		||||
npm run publish:major -- --environment staging
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This will:
 | 
			
		||||
1. _build_ the app's frontend (the output lives in `dist`)
 | 
			
		||||
2. _compile_ the app's contract (the output lives in `build`)
 | 
			
		||||
3. publish the app to the **staging** environment.
 | 
			
		||||
 | 
			
		||||
Sample output:
 | 
			
		||||
```
 | 
			
		||||
 > aragon apm publish major "--environment" "staging"
 | 
			
		||||
 | 
			
		||||
 ✔ Successfully published app.open.aragonpm.eth v1.0.0: 
 | 
			
		||||
 ℹ Contract address: 0xE636bcA5B95e94F749F63E322a04DB59362299F1
 | 
			
		||||
 ℹ Content (ipfs): QmR695Wu5KrHNec7pRP3kPvwYihABDAyVYdX5D5vwLgxCn
 | 
			
		||||
 ℹ Transaction hash: 0x3d752db29cc106e9ff98b260a90615921eb32471425a29ead8cbb830fb224d8
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Note: the contract location is defined in `arapp.json` under `path`.
 | 
			
		||||
Note: you can also deploy a major version with only frontend changes by passing `--only-content`.
 | 
			
		||||
 | 
			
		||||
### Minor/patch version: content only
 | 
			
		||||
 | 
			
		||||
Command:
 | 
			
		||||
```
 | 
			
		||||
npm run publish:patch -- --environment staging
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This will:
 | 
			
		||||
1. _build_ the app's frontend (which lives in `dist`)
 | 
			
		||||
2. publish the app to the **staging** environment.
 | 
			
		||||
 | 
			
		||||
Sample output:
 | 
			
		||||
```
 | 
			
		||||
 ✔ Successfully published app.open.aragonpm.eth v1.1.1: 
 | 
			
		||||
 ℹ Contract address: 0xE636bcA5B95e94F749F63E322a04DB59362299F1
 | 
			
		||||
 ℹ Content (ipfs): QmUYv9cjyNVxCyAJGK2YXjkbzh6u4iW2ak81Z9obdefM1q
 | 
			
		||||
 ℹ Transaction hash: 0x57864d8efd8d439008621b494b19a3e8f876a8a46b38475f9626802f0a1403c2
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Check published versions
 | 
			
		||||
 | 
			
		||||
Command:
 | 
			
		||||
```
 | 
			
		||||
npm run versions -- --environment staging
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Sample output:
 | 
			
		||||
```
 | 
			
		||||
 ℹ app.open.aragonpm.eth has 4 published versions
 | 
			
		||||
 ✔ 1.0.0: 0xE636bcA5B95e94F749F63E322a04DB59362299F1 ipfs:QmR695Wu5KrHNec7pRP3kPvwYihABDAyVYdX5D5vwLgxCn
 | 
			
		||||
 ✔ 1.1.0: 0xE636bcA5B95e94F749F63E322a04DB59362299F1 ipfs:QmSwjUZFpv2c2e9fLoxtgFrAsAmBN4DyQGJp4RcqQcW3z3
 | 
			
		||||
 ✔ 1.1.1: 0xE636bcA5B95e94F749F63E322a04DB59362299F1 ipfs:QmUYv9cjyNVxCyAJGK2YXjkbzh6u4iW2ak81Z9obdefM1q
 | 
			
		||||
 ✔ 2.0.0: 0x74CBbbC932d7C344FCd789Eba24BfD40e52980c9 ipfs:Qmadb3hzwLDKtb93fF367Vg1epkdsLZF4dhpapNYynjgZF
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Using a different Ethereum account
 | 
			
		||||
 | 
			
		||||
To deploy from a different account, you can:
 | 
			
		||||
- define a `~/.aragon/mnemonic.json` file
 | 
			
		||||
    ```
 | 
			
		||||
    {
 | 
			
		||||
        "mnemonic": "explain tackle mirror kit ..."
 | 
			
		||||
    }
 | 
			
		||||
    ```
 | 
			
		||||
    or
 | 
			
		||||
- define a `~/.aragon/${network_name}_key.json` file, for example: `~/.aragon/rinkeby_key.json`
 | 
			
		||||
    ```
 | 
			
		||||
    {
 | 
			
		||||
        "keys": [
 | 
			
		||||
            "a8a54b2d8197bc0b19bb8a084031be71835580a01e70a45a13babd16c9bc1563"
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
    ```
 | 
			
		||||
							
								
								
									
										43
									
								
								apps/proposal/arapp.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								apps/proposal/arapp.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
			
		||||
{
 | 
			
		||||
  "roles": [
 | 
			
		||||
    {
 | 
			
		||||
      "name": "Add proposal",
 | 
			
		||||
      "id": "ADD_PROPOSAL_ROLE",
 | 
			
		||||
      "params": []
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "Vote proposals",
 | 
			
		||||
      "id": "VOTE_PROPOSAL_ROLE",
 | 
			
		||||
      "params": []
 | 
			
		||||
    }, 
 | 
			
		||||
    {
 | 
			
		||||
      "name": "Add contribution",
 | 
			
		||||
      "id": "ADD_CONTRIBUTION_ROLE",
 | 
			
		||||
      "params": []
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "name": "Manage contributors",
 | 
			
		||||
      "id": "MANAGE_CONTRIBUTORS_ROLE",
 | 
			
		||||
      "params": []
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "environments": {
 | 
			
		||||
    "default": {
 | 
			
		||||
      "network": "development",
 | 
			
		||||
      "appName": "proposal.aragonpm.eth"
 | 
			
		||||
    },
 | 
			
		||||
    "staging": {
 | 
			
		||||
      "registry": "0x98df287b6c145399aaa709692c8d308357bc085d",
 | 
			
		||||
      "appName": "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"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										132
									
								
								apps/proposal/contracts/Proposal.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								apps/proposal/contracts/Proposal.sol
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,132 @@
 | 
			
		||||
pragma solidity ^0.4.24;
 | 
			
		||||
 | 
			
		||||
import "@aragon/os/contracts/apps/AragonApp.sol";
 | 
			
		||||
import "@aragon/os/contracts/kernel/IKernel.sol";
 | 
			
		||||
 | 
			
		||||
interface IContributor {
 | 
			
		||||
  function getContributorAddressById(uint256 contributorId) public view returns (address);
 | 
			
		||||
  function getContributorIdByAddress(address contributorAccount) public view returns (uint256);
 | 
			
		||||
  function exists(uint256 contributorId) public view returns (bool);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface IContribution {
 | 
			
		||||
  function add(uint256 amount, address contributor, 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;
 | 
			
		||||
  bytes32 public constant CONTRIBUTOR_APP_ID = 0xe9140f1e39c8a1d04167c3b710688a3eecea2976f34735c8eb98956f4764635b;
 | 
			
		||||
  bytes32 public constant CONTRIBUTION_APP_ID = 0x7fcf91283b719b30c2fa954ff0da021e1b91aed09d7aa13df5e8078a4a1007eb;
 | 
			
		||||
 | 
			
		||||
  struct Proposal {
 | 
			
		||||
    address creatorAccount;
 | 
			
		||||
    uint contributorId;
 | 
			
		||||
    uint votesCount;
 | 
			
		||||
    uint votesNeeded;
 | 
			
		||||
    uint256 amount;
 | 
			
		||||
    bool executed;
 | 
			
		||||
    bytes32 hashDigest;
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
  function initialize() public onlyInit {
 | 
			
		||||
    initialized();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function getContributorContract() public view returns (address) {
 | 
			
		||||
    return IKernel(kernel()).getApp(KERNEL_APP_ADDR_NAMESPACE, CONTRIBUTOR_APP_ID);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function getContributionContract() public view returns (address) {
 | 
			
		||||
    return IKernel(kernel()).getApp(KERNEL_APP_ADDR_NAMESPACE, CONTRIBUTION_APP_ID);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function addProposal(uint contributorId, uint256 amount, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(ADD_PROPOSAL_ROLE) {
 | 
			
		||||
    require(IContributor(getContributorContract()).exists(contributorId), 'CONTRIBUTOR_NOT_FOUND');
 | 
			
		||||
 | 
			
		||||
    uint256 proposalId = proposalsCount + 1;
 | 
			
		||||
    uint256 _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(uint proposalId) public view returns (uint256 id, address creatorAccount, uint256 contributorId, uint256 votesCount, uint256 votesNeeded, uint256 amount, bool executed, bytes32 hashDigest, 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.hashDigest, 
 | 
			
		||||
      p.hashFunction,
 | 
			
		||||
      p.hashSize,
 | 
			
		||||
      p.voterIds,
 | 
			
		||||
      p.exists
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function vote(uint256 proposalId) public isInitialized auth(VOTE_PROPOSAL_ROLE) {
 | 
			
		||||
    Proposal storage p = proposals[proposalId];
 | 
			
		||||
    require(!p.executed, 'ALREADY_EXECUTED');
 | 
			
		||||
    uint256 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(uint256[] _proposalIds) public isInitialized auth(VOTE_PROPOSAL_ROLE) {
 | 
			
		||||
    for (uint256 i = 0; i < _proposalIds.length; i++) {
 | 
			
		||||
      vote(_proposalIds[i]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function executeProposal(uint proposalId) private {
 | 
			
		||||
    Proposal storage p = proposals[proposalId];
 | 
			
		||||
    require(!p.executed, 'ALREADY_EXECUTED');
 | 
			
		||||
    require(p.votesCount >= p.votesNeeded, 'MISSING_VOTES');
 | 
			
		||||
    
 | 
			
		||||
    address contributorAccount = IContributor(getContributorContract()).getContributorAddressById(p.contributorId);
 | 
			
		||||
    IContribution(getContributionContract()).add(p.amount, contributorAccount, p.hashDigest, p.hashFunction, p.hashSize);
 | 
			
		||||
    p.executed = true;
 | 
			
		||||
    emit ProposalExecuted(proposalId, p.contributorId, p.amount);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										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)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21093
									
								
								apps/proposal/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										21093
									
								
								apps/proposal/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										28
									
								
								apps/proposal/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								apps/proposal/package.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "kredits-proposal",
 | 
			
		||||
  "version": "1.0.0",
 | 
			
		||||
  "description": "",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@aragon/os": "^4.1.0",
 | 
			
		||||
    "@aragon/cli": "^5.5.0"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
  },
 | 
			
		||||
  "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": "",
 | 
			
		||||
    "test": "aragon contracts test",
 | 
			
		||||
    "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"
 | 
			
		||||
  },
 | 
			
		||||
  "keywords": []
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										63
									
								
								apps/proposal/truffle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								apps/proposal/truffle.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
			
		||||
/**
 | 
			
		||||
 * https://github.com/aragon/aragonOS/blob/v4.0.0/truffle-config.js
 | 
			
		||||
 */
 | 
			
		||||
const homedir = require('homedir')
 | 
			
		||||
const path = require('path')
 | 
			
		||||
 | 
			
		||||
const HDWalletProvider = require('truffle-hdwallet-provider')
 | 
			
		||||
const HDWalletProviderPrivkey = require('truffle-hdwallet-provider-privkey')
 | 
			
		||||
 | 
			
		||||
const DEFAULT_MNEMONIC = 'explain tackle mirror kit van hammer degree position ginger unfair soup bonus'
 | 
			
		||||
 | 
			
		||||
const defaultRPC = (network) =>
 | 
			
		||||
  `https://${network}.infura.io`
 | 
			
		||||
 | 
			
		||||
const configFilePath = (filename) =>
 | 
			
		||||
  path.join(homedir(), `.aragon/${filename}`)
 | 
			
		||||
 | 
			
		||||
const mnemonic = () => {
 | 
			
		||||
  try {
 | 
			
		||||
    return require(configFilePath('mnemonic.json')).mnemonic
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    return DEFAULT_MNEMONIC
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const settingsForNetwork = (network) => {
 | 
			
		||||
  try {
 | 
			
		||||
    return require(configFilePath(`${network}_key.json`))
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    return { }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Lazily loaded provider
 | 
			
		||||
const providerForNetwork = (network) => (
 | 
			
		||||
  () => {
 | 
			
		||||
    let { rpc, keys } = settingsForNetwork(network)
 | 
			
		||||
    rpc = rpc || defaultRPC(network)
 | 
			
		||||
 | 
			
		||||
    if (!keys || keys.length == 0) {
 | 
			
		||||
      return new HDWalletProvider(mnemonic(), rpc)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return new HDWalletProviderPrivkey(keys, rpc)
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
module.exports = {
 | 
			
		||||
  networks: {
 | 
			
		||||
    development: {
 | 
			
		||||
      host: 'localhost',
 | 
			
		||||
      port: 8545,
 | 
			
		||||
      network_id: '*'
 | 
			
		||||
    },
 | 
			
		||||
    mainnet: {
 | 
			
		||||
      network_id: 1,
 | 
			
		||||
      provider: providerForNetwork('mainnet')
 | 
			
		||||
    },
 | 
			
		||||
    rinkeby: {
 | 
			
		||||
      network_id: 4,
 | 
			
		||||
      provider: providerForNetwork('rinkeby')
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
							
								
								
									
										162
									
								
								apps/token/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								apps/token/README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,162 @@
 | 
			
		||||
# Aragon React Boilerplate
 | 
			
		||||
 | 
			
		||||
> 🕵️ [Find more boilerplates using GitHub](https://github.com/search?q=topic:aragon-boilerplate) | 
 | 
			
		||||
> ✨ [Official boilerplates](https://github.com/search?q=topic:aragon-boilerplate+org:aragon)
 | 
			
		||||
 | 
			
		||||
React boilerplate for Aragon applications.
 | 
			
		||||
 | 
			
		||||
This boilerplate also includes a fully working example app, complete with a background worker and a front-end in React (with Aragon UI).
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
```sh
 | 
			
		||||
aragon init app.aragonpm.eth react
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Running your app
 | 
			
		||||
 | 
			
		||||
### Using HTTP
 | 
			
		||||
 | 
			
		||||
Running your app using HTTP will allow for a faster development process of your app's front-end, as it can be hot-reloaded without the need to execute `aragon run` every time a change is made.
 | 
			
		||||
 | 
			
		||||
- First start your app's development server running `npm run start:app`, and keep that process running. By default it will rebuild the app and reload the server when changes to the source are made.
 | 
			
		||||
 | 
			
		||||
- After that, you can run `npm run start:aragon:http` which will compile your app's contracts, publish the app locally and create a DAO. You will need to stop it and run it again after making changes to your smart contracts.
 | 
			
		||||
 | 
			
		||||
Changes to the app's background script (`app/script.js`) cannot be hot-reloaded, after making changes to the script, you will need to either restart the development server (`npm run start:app`) or rebuild the script `npm run build:script`.
 | 
			
		||||
 | 
			
		||||
### Using IPFS
 | 
			
		||||
 | 
			
		||||
Running your app using IPFS will mimic the production environment that will be used for running your app. `npm run start:aragon:ipfs` will run your app using IPFS. Whenever a change is made to any file in your front-end, a new version of the app needs to be published, so the command needs to be restarted.
 | 
			
		||||
 | 
			
		||||
## What's in the box?
 | 
			
		||||
 | 
			
		||||
### npm Scripts
 | 
			
		||||
 | 
			
		||||
- **start** or **start:aragon:ipfs**: Runs your app inside a DAO served from IPFS
 | 
			
		||||
- **start:aragon:http**: Runs your app inside a DAO served with HTTP (hot reloading)
 | 
			
		||||
- **start:app**: Starts a development server for your app
 | 
			
		||||
- **compile**: Compile the smart contracts
 | 
			
		||||
- **build**: Builds the front-end and background script
 | 
			
		||||
- **build:app**: Builds the front-end
 | 
			
		||||
- **build:script**: Builds the background script
 | 
			
		||||
- **test**: Runs tests for the contracts
 | 
			
		||||
- **publish:patch**: Release a patch version to aragonPM (only frontend/content changes allowed)
 | 
			
		||||
- **publish:minor**: Release a minor version to aragonPM (only frontend/content changes allowed)
 | 
			
		||||
- **publish:major**: Release a major version to aragonPM (frontend **and** contract changes)
 | 
			
		||||
- **versions**: Check the currently installed versions of the app
 | 
			
		||||
 | 
			
		||||
### Libraries
 | 
			
		||||
 | 
			
		||||
- [**@aragon/os**](https://github.com/aragon/aragonos): Aragon interfaces
 | 
			
		||||
- [**@aragon/client**](https://github.com/aragon/aragon.js/tree/master/packages/aragon-client): Wrapper for Aragon application RPC
 | 
			
		||||
- [**@aragon/ui**](https://github.com/aragon/aragon-ui): Aragon UI components (in React)
 | 
			
		||||
 | 
			
		||||
## Publish
 | 
			
		||||
 | 
			
		||||
This app has 3 environments defined in `arapp.json`:
 | 
			
		||||
 | 
			
		||||
| Environment   | Network   |
 | 
			
		||||
|---            |---        |
 | 
			
		||||
| default       | localhost |
 | 
			
		||||
| staging       | rinkeby   |
 | 
			
		||||
| production    | mainnet   |
 | 
			
		||||
 | 
			
		||||
Prerequisites:
 | 
			
		||||
- ENS Registry address
 | 
			
		||||
 | 
			
		||||
Note: the `default` environment which points to `localhost` does not have an ENS Registry address specified because the `@aragon/cli` will default the value to `0xB9462EF3441346dBc6E49236Edbb0dF207db09B7` (the ENS Registry pre-deployed on the local development chain).
 | 
			
		||||
 | 
			
		||||
### Introduction to environments
 | 
			
		||||
 | 
			
		||||
Environments are defined in `arapp.json`, for example `staging` points to:
 | 
			
		||||
- an ENS registry (`0x314159265dd8dbb310642f98f50c066173c1259b`)
 | 
			
		||||
- an APM registry (`open.aragonpm.eth`)
 | 
			
		||||
- an APM repository (`app`)
 | 
			
		||||
- an Ethereum network (`rinkeby`)
 | 
			
		||||
- an Ethereum websockets provider (`wss://rinkeby.eth.aragon.network/ws` - to **read** from the blockchain)
 | 
			
		||||
 | 
			
		||||
The `rinkeby` network is further defined in `truffle.js`, and has:
 | 
			
		||||
- an Ethereum provider (to **write** to the blockchain):
 | 
			
		||||
    - an address (`https://rinkeby.infura.io`)
 | 
			
		||||
    - an Ethereum Account (`0xb4124cEB3451635DAcedd11767f004d8a28c6eE7`)
 | 
			
		||||
    (which is the first account generated from the `DEFAULT_MNEMONIC` variable, to use a different account see [here](#Using-a-different-Ethereum-account))
 | 
			
		||||
 | 
			
		||||
### Major version: content + contract
 | 
			
		||||
 | 
			
		||||
Command:
 | 
			
		||||
```
 | 
			
		||||
npm run publish:major -- --environment staging
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This will:
 | 
			
		||||
1. _build_ the app's frontend (the output lives in `dist`)
 | 
			
		||||
2. _compile_ the app's contract (the output lives in `build`)
 | 
			
		||||
3. publish the app to the **staging** environment.
 | 
			
		||||
 | 
			
		||||
Sample output:
 | 
			
		||||
```
 | 
			
		||||
 > aragon apm publish major "--environment" "staging"
 | 
			
		||||
 | 
			
		||||
 ✔ Successfully published app.open.aragonpm.eth v1.0.0: 
 | 
			
		||||
 ℹ Contract address: 0xE636bcA5B95e94F749F63E322a04DB59362299F1
 | 
			
		||||
 ℹ Content (ipfs): QmR695Wu5KrHNec7pRP3kPvwYihABDAyVYdX5D5vwLgxCn
 | 
			
		||||
 ℹ Transaction hash: 0x3d752db29cc106e9ff98b260a90615921eb32471425a29ead8cbb830fb224d8
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Note: the contract location is defined in `arapp.json` under `path`.
 | 
			
		||||
Note: you can also deploy a major version with only frontend changes by passing `--only-content`.
 | 
			
		||||
 | 
			
		||||
### Minor/patch version: content only
 | 
			
		||||
 | 
			
		||||
Command:
 | 
			
		||||
```
 | 
			
		||||
npm run publish:patch -- --environment staging
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This will:
 | 
			
		||||
1. _build_ the app's frontend (which lives in `dist`)
 | 
			
		||||
2. publish the app to the **staging** environment.
 | 
			
		||||
 | 
			
		||||
Sample output:
 | 
			
		||||
```
 | 
			
		||||
 ✔ Successfully published app.open.aragonpm.eth v1.1.1: 
 | 
			
		||||
 ℹ Contract address: 0xE636bcA5B95e94F749F63E322a04DB59362299F1
 | 
			
		||||
 ℹ Content (ipfs): QmUYv9cjyNVxCyAJGK2YXjkbzh6u4iW2ak81Z9obdefM1q
 | 
			
		||||
 ℹ Transaction hash: 0x57864d8efd8d439008621b494b19a3e8f876a8a46b38475f9626802f0a1403c2
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Check published versions
 | 
			
		||||
 | 
			
		||||
Command:
 | 
			
		||||
```
 | 
			
		||||
npm run versions -- --environment staging
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Sample output:
 | 
			
		||||
```
 | 
			
		||||
 ℹ app.open.aragonpm.eth has 4 published versions
 | 
			
		||||
 ✔ 1.0.0: 0xE636bcA5B95e94F749F63E322a04DB59362299F1 ipfs:QmR695Wu5KrHNec7pRP3kPvwYihABDAyVYdX5D5vwLgxCn
 | 
			
		||||
 ✔ 1.1.0: 0xE636bcA5B95e94F749F63E322a04DB59362299F1 ipfs:QmSwjUZFpv2c2e9fLoxtgFrAsAmBN4DyQGJp4RcqQcW3z3
 | 
			
		||||
 ✔ 1.1.1: 0xE636bcA5B95e94F749F63E322a04DB59362299F1 ipfs:QmUYv9cjyNVxCyAJGK2YXjkbzh6u4iW2ak81Z9obdefM1q
 | 
			
		||||
 ✔ 2.0.0: 0x74CBbbC932d7C344FCd789Eba24BfD40e52980c9 ipfs:Qmadb3hzwLDKtb93fF367Vg1epkdsLZF4dhpapNYynjgZF
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Using a different Ethereum account
 | 
			
		||||
 | 
			
		||||
To deploy from a different account, you can:
 | 
			
		||||
- define a `~/.aragon/mnemonic.json` file
 | 
			
		||||
    ```
 | 
			
		||||
    {
 | 
			
		||||
        "mnemonic": "explain tackle mirror kit ..."
 | 
			
		||||
    }
 | 
			
		||||
    ```
 | 
			
		||||
    or
 | 
			
		||||
- define a `~/.aragon/${network_name}_key.json` file, for example: `~/.aragon/rinkeby_key.json`
 | 
			
		||||
    ```
 | 
			
		||||
    {
 | 
			
		||||
        "keys": [
 | 
			
		||||
            "a8a54b2d8197bc0b19bb8a084031be71835580a01e70a45a13babd16c9bc1563"
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
    ```
 | 
			
		||||
							
								
								
									
										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": "token.aragonpm.eth"
 | 
			
		||||
    },
 | 
			
		||||
    "staging": {
 | 
			
		||||
      "registry": "0x98df287b6c145399aaa709692c8d308357bc085d",
 | 
			
		||||
      "appName": "token.open.aragonpm.eth",
 | 
			
		||||
      "wsRPC": "wss://rinkeby.eth.aragon.network/ws",
 | 
			
		||||
      "network": "rinkeby"
 | 
			
		||||
    },
 | 
			
		||||
    "production": {
 | 
			
		||||
      "registry": "0x314159265dd8dbb310642f98f50c066173c1259b",
 | 
			
		||||
      "appName": "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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								apps/token/contracts/Token.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								apps/token/contracts/Token.sol
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
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");
 | 
			
		||||
 | 
			
		||||
  event LogMint(address indexed recipient, uint256 amount, uint256 contributionId);
 | 
			
		||||
  
 | 
			
		||||
  function initialize() public onlyInit {
 | 
			
		||||
    initialized();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function mintFor(address contributorAccount, uint256 amount, uint256 contributionId) public isInitialized auth(MINT_TOKEN_ROLE) {
 | 
			
		||||
    _mint(contributorAccount, amount);
 | 
			
		||||
    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.4;
 | 
			
		||||
 | 
			
		||||
contract Migrations {
 | 
			
		||||
  address public owner;
 | 
			
		||||
  uint public last_completed_migration;
 | 
			
		||||
 | 
			
		||||
  modifier restricted() {
 | 
			
		||||
    if (msg.sender == owner) _;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function Migrations() {
 | 
			
		||||
    owner = msg.sender;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function setCompleted(uint completed) restricted {
 | 
			
		||||
    last_completed_migration = completed;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function upgrade(address new_address) 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)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13482
									
								
								apps/token/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										13482
									
								
								apps/token/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										28
									
								
								apps/token/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								apps/token/package.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "kredits-token",
 | 
			
		||||
  "version": "1.0.0",
 | 
			
		||||
  "description": "",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@aragon/os": "^4.1.0",
 | 
			
		||||
    "@aragon/cli": "^5.5.0"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
  },
 | 
			
		||||
  "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": "",
 | 
			
		||||
    "test": "aragon contracts test",
 | 
			
		||||
    "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"
 | 
			
		||||
  },
 | 
			
		||||
  "keywords": []
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								apps/token/test/app.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								apps/token/test/app.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
const CounterApp = artifacts.require('CounterApp.sol')
 | 
			
		||||
 | 
			
		||||
contract('CounterApp', (accounts) => {
 | 
			
		||||
  it('should be tested')
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										63
									
								
								apps/token/truffle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								apps/token/truffle.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
			
		||||
/**
 | 
			
		||||
 * https://github.com/aragon/aragonOS/blob/v4.0.0/truffle-config.js
 | 
			
		||||
 */
 | 
			
		||||
const homedir = require('homedir')
 | 
			
		||||
const path = require('path')
 | 
			
		||||
 | 
			
		||||
const HDWalletProvider = require('truffle-hdwallet-provider')
 | 
			
		||||
const HDWalletProviderPrivkey = require('truffle-hdwallet-provider-privkey')
 | 
			
		||||
 | 
			
		||||
const DEFAULT_MNEMONIC = 'explain tackle mirror kit van hammer degree position ginger unfair soup bonus'
 | 
			
		||||
 | 
			
		||||
const defaultRPC = (network) =>
 | 
			
		||||
  `https://${network}.infura.io`
 | 
			
		||||
 | 
			
		||||
const configFilePath = (filename) =>
 | 
			
		||||
  path.join(homedir(), `.aragon/${filename}`)
 | 
			
		||||
 | 
			
		||||
const mnemonic = () => {
 | 
			
		||||
  try {
 | 
			
		||||
    return require(configFilePath('mnemonic.json')).mnemonic
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    return DEFAULT_MNEMONIC
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const settingsForNetwork = (network) => {
 | 
			
		||||
  try {
 | 
			
		||||
    return require(configFilePath(`${network}_key.json`))
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    return { }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Lazily loaded provider
 | 
			
		||||
const providerForNetwork = (network) => (
 | 
			
		||||
  () => {
 | 
			
		||||
    let { rpc, keys } = settingsForNetwork(network)
 | 
			
		||||
    rpc = rpc || defaultRPC(network)
 | 
			
		||||
 | 
			
		||||
    if (!keys || keys.length == 0) {
 | 
			
		||||
      return new HDWalletProvider(mnemonic(), rpc)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return new HDWalletProviderPrivkey(keys, rpc)
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
module.exports = {
 | 
			
		||||
  networks: {
 | 
			
		||||
    development: {
 | 
			
		||||
      host: 'localhost',
 | 
			
		||||
      port: 8545,
 | 
			
		||||
      network_id: '*'
 | 
			
		||||
    },
 | 
			
		||||
    mainnet: {
 | 
			
		||||
      network_id: 1,
 | 
			
		||||
      provider: providerForNetwork('mainnet')
 | 
			
		||||
    },
 | 
			
		||||
    rinkeby: {
 | 
			
		||||
      network_id: 4,
 | 
			
		||||
      provider: providerForNetwork('rinkeby')
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								arapp.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								arapp.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
			
		||||
{
 | 
			
		||||
  "roles": [
 | 
			
		||||
    {
 | 
			
		||||
      "name": "Add contributions",
 | 
			
		||||
      "id": "ADD_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": {
 | 
			
		||||
    "rinkeby": {
 | 
			
		||||
      "wsRPC": "wss://rinkeby.eth.aragon.network/ws",
 | 
			
		||||
      "registry": "0x98Df287B6C145399Aaa709692c8D308357bC085D",
 | 
			
		||||
      "appName": "dummy.open.aragonpm.eth",
 | 
			
		||||
      "network": "rinkeby"
 | 
			
		||||
    },
 | 
			
		||||
    "rpc": {
 | 
			
		||||
      "network": "rpc",
 | 
			
		||||
      "appName": "dummy.aragonpm.eth"
 | 
			
		||||
    },
 | 
			
		||||
    "default": {
 | 
			
		||||
      "network": "rpc",
 | 
			
		||||
      "appName": "dummy.aragonpm.eth"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "path": "contracts/misc/DummyApp.sol"
 | 
			
		||||
}
 | 
			
		||||
@ -1,126 +0,0 @@
 | 
			
		||||
pragma solidity ^0.4.19;
 | 
			
		||||
 | 
			
		||||
import "zeppelin-solidity/contracts/token/ERC721/ERC721Token.sol";
 | 
			
		||||
import './upgradeable/Upgradeable.sol';
 | 
			
		||||
 | 
			
		||||
// ToDo: only load interfaces
 | 
			
		||||
import './Token.sol';
 | 
			
		||||
import './Contributors.sol';
 | 
			
		||||
 | 
			
		||||
contract Contribution is Upgradeable, ERC721Token {
 | 
			
		||||
 | 
			
		||||
  struct ContributionData {
 | 
			
		||||
    address contributor;
 | 
			
		||||
    uint amount;
 | 
			
		||||
    bool claimed;
 | 
			
		||||
    bytes32 hashDigest;
 | 
			
		||||
    uint8 hashFunction;
 | 
			
		||||
    uint8 hashSize;
 | 
			
		||||
    string tokenMetadataURL;
 | 
			
		||||
    uint claimAfterBlock;
 | 
			
		||||
    bool exists;
 | 
			
		||||
  }
 | 
			
		||||
  string internal name_;
 | 
			
		||||
  string internal symbol_;
 | 
			
		||||
 | 
			
		||||
  mapping(uint256 => address) contributionOwner;
 | 
			
		||||
  mapping(address => uint256[]) ownedContributions;
 | 
			
		||||
 | 
			
		||||
  mapping(uint256 => ContributionData) public contributions;
 | 
			
		||||
  uint256 public contributionsCount;
 | 
			
		||||
 | 
			
		||||
  event ContributionAdded(uint256 id, address indexed contributor, uint256 amount);
 | 
			
		||||
  event ContributionClaimed(uint256 id, address indexed contributor, uint256 amount);
 | 
			
		||||
 | 
			
		||||
  modifier coreOnly() { 
 | 
			
		||||
    require(contributorsContract().addressIsCore(msg.sender));
 | 
			
		||||
    _;
 | 
			
		||||
  }
 | 
			
		||||
  modifier contributorOnly() { 
 | 
			
		||||
    require(contributorsContract().addressExists(msg.sender));
 | 
			
		||||
    _;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  function contributorsContract() view public returns (Contributors) {
 | 
			
		||||
    return Contributors(registry.getProxyFor('Contributors'));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function tokenContract() view public returns (Token) {
 | 
			
		||||
    return Token(registry.getProxyFor('Token'));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function name() external view returns (string) {
 | 
			
		||||
    return name_;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function symbol() external view returns (string) {
 | 
			
		||||
    return symbol_;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function ownerOf(uint256 contributionId) public view returns (address) {
 | 
			
		||||
    require(exists(contributionId));
 | 
			
		||||
    return contributions[contributionId].contributor;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function balanceOf(address contributor) public view returns (uint) {
 | 
			
		||||
    return ownedContributions[contributor].length;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function tokenOfOwnerByIndex(address contributor, uint index) public view returns (uint) {
 | 
			
		||||
    return ownedContributions[contributor][index];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function tokenMetadata(uint contributionId) public view returns (string) {
 | 
			
		||||
    return contributions[contributionId].tokenMetadataURL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function getContribution(uint contributionId) public view returns (uint256 id, address contributor, uint256 amount, bool claimed, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint claimAfterBlock, bool exists) {
 | 
			
		||||
    id = contributionId;
 | 
			
		||||
    ContributionData storage c = contributions[id];
 | 
			
		||||
    return (
 | 
			
		||||
      id,
 | 
			
		||||
      c.contributor,
 | 
			
		||||
      c.amount, 
 | 
			
		||||
      c.claimed, 
 | 
			
		||||
      c.hashDigest,
 | 
			
		||||
      c.hashFunction,
 | 
			
		||||
      c.hashSize,
 | 
			
		||||
      c.claimAfterBlock,
 | 
			
		||||
      c.exists
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function add(uint256 amount, address contributor, uint256 blocksToWait) public coreOnly {
 | 
			
		||||
    uint contributionId = contributionsCount + 1;
 | 
			
		||||
    ContributionData storage c = contributions[contributionId];
 | 
			
		||||
    c.exists = true;
 | 
			
		||||
    c.amount = amount;
 | 
			
		||||
    c.claimed = false;
 | 
			
		||||
    c.contributor = contributor;
 | 
			
		||||
    c.claimAfterBlock = block.number + blocksToWait;
 | 
			
		||||
 | 
			
		||||
    contributionsCount++;
 | 
			
		||||
 | 
			
		||||
    contributionOwner[contributionId] = contributor;
 | 
			
		||||
    ownedContributions[contributor].push(contributionId);
 | 
			
		||||
  
 | 
			
		||||
    ContributionAdded(contributionId, contributor, amount);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function claim(uint256 contributionId) public {
 | 
			
		||||
    ContributionData storage c = contributions[contributionId];
 | 
			
		||||
    require(c.exists);
 | 
			
		||||
    require(!c.claimed);
 | 
			
		||||
    require(block.number > c.claimAfterBlock);
 | 
			
		||||
    c.claimed = true;
 | 
			
		||||
    tokenContract().mintFor(c.contributor, c.amount, contributionId);
 | 
			
		||||
    
 | 
			
		||||
    ContributionClaimed(contributionId, c.contributor, c.amount);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function exists(uint256 contributionId) view public returns (bool) {
 | 
			
		||||
    return contributions[contributionId].exists;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										85
									
								
								contracts/KreditsKit.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								contracts/KreditsKit.sol
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,85 @@
 | 
			
		||||
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/os/contracts/acl/ACLSyntaxSugar.sol";
 | 
			
		||||
 | 
			
		||||
import "@aragon/kits-base/contracts/KitBase.sol";
 | 
			
		||||
import "./misc/APMNamehashOpen.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, APMNamehashOpen, ACLSyntaxSugar  {
 | 
			
		||||
    bytes32 public contributorAppId = apmNamehash("contributor"); // 0xe9140f1e39c8a1d04167c3b710688a3eecea2976f34735c8eb98956f4764635b
 | 
			
		||||
    bytes32 public contributionAppId = apmNamehash("contribution"); // 0x7fcf91283b719b30c2fa954ff0da021e1b91aed09d7aa13df5e8078a4a1007eb 
 | 
			
		||||
    bytes32 public tokenAppId = apmNamehash("token"); // 0xe04a882e7a6adf5603207d545ea49aec17e6b936c4d9eae3d74dbe482264991a 
 | 
			
		||||
    bytes32 public proposalAppId = apmNamehash("proposal"); // 0xaf5fe5c3b0d9581ee88974bbc8699e6fa71efd1b321e44b2227103c9ef21dbdb 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    event DeployInstance(address dao);
 | 
			
		||||
    event InstalledApp(address dao, address appProxy, bytes32 appId);
 | 
			
		||||
 | 
			
		||||
    constructor (DAOFactory _fac, ENS _ens) public KitBase(_fac, _ens) {}
 | 
			
		||||
 | 
			
		||||
    function newInstance() public returns (Kernel dao, ERCProxy proxy) {
 | 
			
		||||
        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, contributorAppId));
 | 
			
		||||
        contributor.initialize(root);
 | 
			
		||||
        acl.createPermission(root, contributor, contributor.MANAGE_CONTRIBUTORS_ROLE(), root);
 | 
			
		||||
        
 | 
			
		||||
        Token token = Token(_installApp(dao, tokenAppId));
 | 
			
		||||
        token.initialize();
 | 
			
		||||
        
 | 
			
		||||
        Contribution contribution = Contribution(_installApp(dao, contributionAppId));
 | 
			
		||||
        contribution.initialize();
 | 
			
		||||
        
 | 
			
		||||
        Proposal proposal = Proposal(_installApp(dao, proposalAppId));
 | 
			
		||||
        proposal.initialize();
 | 
			
		||||
 | 
			
		||||
        acl.createPermission(root, contribution, contribution.ADD_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(root, contribution, contribution.ADD_CONTRIBUTION_ROLE(), params);
 | 
			
		||||
 | 
			
		||||
        //acl.setPermissionManager(this, proposal, proposal.VOTE_PROPOSAL_ROLE();
 | 
			
		||||
        acl.createPermission(root, proposal, proposal.VOTE_PROPOSAL_ROLE(), this);
 | 
			
		||||
        acl.grantPermissionP(root, proposal, proposal.VOTE_PROPOSAL_ROLE(), params);
 | 
			
		||||
        
 | 
			
		||||
        acl.createPermission(root, proposal, proposal.ADD_PROPOSAL_ROLE(), this);
 | 
			
		||||
        acl.grantPermissionP(root, proposal, proposal.ADD_PROPOSAL_ROLE(), params);
 | 
			
		||||
 | 
			
		||||
        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.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,133 +0,0 @@
 | 
			
		||||
pragma solidity ^0.4.18;
 | 
			
		||||
 | 
			
		||||
// ToDo: only load interfaces
 | 
			
		||||
import './Token.sol';
 | 
			
		||||
import './Contributors.sol';
 | 
			
		||||
import './Contribution.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 contributionContract() view public returns (Contribution) {
 | 
			
		||||
    return Contribution(registry.getProxyFor('Contribution'));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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 batchVote(uint256[] _proposalIds) public coreOnly {
 | 
			
		||||
    for (uint256 i = 0; i < _proposalIds.length; i++) {
 | 
			
		||||
      vote(_proposalIds[i]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function executeProposal(uint proposalId) private {
 | 
			
		||||
    var p = proposals[proposalId];
 | 
			
		||||
    require(!p.executed);
 | 
			
		||||
    require(p.votesCount >= p.votesNeeded);
 | 
			
		||||
    address recipientAddress = contributorsContract().getContributorAddressById(p.contributorId);
 | 
			
		||||
    contributionContract().add(p.amount, recipientAddress, 0);
 | 
			
		||||
    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('Contribution') 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();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
pragma solidity ^0.4.17;
 | 
			
		||||
pragma solidity ^0.4.4;
 | 
			
		||||
 | 
			
		||||
contract Migrations {
 | 
			
		||||
  address public owner;
 | 
			
		||||
@ -8,7 +8,7 @@ contract Migrations {
 | 
			
		||||
    if (msg.sender == owner) _;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function Migrations() public {
 | 
			
		||||
  function constructor() public {
 | 
			
		||||
    owner = msg.sender;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -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));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
										
											
												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 +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":"contributionContract","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"},{"constant":false,"inputs":[{"name":"_proposalIds","type":"uint256[]"}],"name":"batchVote","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"}]
 | 
			
		||||
@ -1 +1 @@
 | 
			
		||||
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"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":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"recipient","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"proposalId","type":"uint256"}],"name":"LogMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":false,"inputs":[{"name":"sender","type":"address"}],"name":"initialize","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"contributorAccount","type":"address"},{"name":"amount","type":"uint256"},{"name":"proposalId","type":"uint256"}],"name":"mintFor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
 | 
			
		||||
[{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"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":"_foo","outputs":[{"name":"","type":"uint256"}],"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":"MINT_TOKEN_ROLE","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":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":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"recipient","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"contributionId","type":"uint256"}],"name":"LogMint","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":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"foo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"mintFor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
{"42":"0x205fe1b3dac678b594c5f0535e7d158e38591f93","100":"0xa7fc9b1f678c41396b53904f94f50a42ff44d826"}
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
{"42":"0x9fd66ee78a5ebe86006f12b37ff59c63f9caa15b","100":"0x95d3bd7d136bb0b7ac9988097e964236f8a9976e"}
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
{"42":"0xc270e6ea4fe303df9f1a3d4a132ac425264082e7","100":"0x7458dea485d9d8301e3ce43e8a1ec1456be5ba83"}
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
{"42":"0xf71ccf7ab48044ef9ae0b5e6983dbd3266b78b36","100":"0x3fc29fbe40c2d0ca78c7e81342f00226650fe2ad"}
 | 
			
		||||
							
								
								
									
										1
									
								
								lib/addresses/dao.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								lib/addresses/dao.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
{"23827572":"0xe4e0e7fe54d9189df29a80c07ab733fc9a212761","65047207":"0xdbe26ae4a434472a7474db60cc3e3c97a57bbf38"}
 | 
			
		||||
@ -46,6 +46,26 @@ class Contribution extends Base {
 | 
			
		||||
        return RSVP.all(contributions);
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  addContribution(contributionAttr, callOptions = {}) {
 | 
			
		||||
    let json = ContributionSerializer.serialize(contributionAttr);
 | 
			
		||||
    // TODO: validate against schema
 | 
			
		||||
 | 
			
		||||
    return this.ipfs
 | 
			
		||||
      .add(json)
 | 
			
		||||
      .then((ipfsHashAttr) => {
 | 
			
		||||
        let contribution = [
 | 
			
		||||
          contributionAttr.amount,
 | 
			
		||||
          contributionAttr.contributorAccount,
 | 
			
		||||
          ipfsHashAttr.hashDigest,
 | 
			
		||||
          ipfsHashAttr.hashFunction,
 | 
			
		||||
          ipfsHashAttr.hashSize,
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        console.log(contribution);
 | 
			
		||||
        return this.functions.add(...contribution, callOptions);
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = Contribution;
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
module.exports = {
 | 
			
		||||
  Contributors: require('./contributor'),
 | 
			
		||||
  Contributor: require('./contributor'),
 | 
			
		||||
  Contribution: require('./contribution'),
 | 
			
		||||
  Operator: require('./operator'),
 | 
			
		||||
  Proposal: require('./proposal'),
 | 
			
		||||
  Token: require('./token'),
 | 
			
		||||
  Registry: require('./registry')
 | 
			
		||||
  Kernel: require('./kernel')
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										21
									
								
								lib/contracts/kernel.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								lib/contracts/kernel.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
const Base = require('./base');
 | 
			
		||||
 | 
			
		||||
KERNEL_APP_ADDR_NAMESPACE = '0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb';
 | 
			
		||||
 | 
			
		||||
class Kernel extends Base {
 | 
			
		||||
 | 
			
		||||
  getApp(appName) {
 | 
			
		||||
    return this.functions.getApp(KERNEL_APP_ADDR_NAMESPACE, this.appNamehash(appName));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  appNamehash(appName) {
 | 
			
		||||
    return {
 | 
			
		||||
      Contributor: '0xe9140f1e39c8a1d04167c3b710688a3eecea2976f34735c8eb98956f4764635b',
 | 
			
		||||
      Contribution: '0x7fcf91283b719b30c2fa954ff0da021e1b91aed09d7aa13df5e8078a4a1007eb',
 | 
			
		||||
      Token: '0xe04a882e7a6adf5603207d545ea49aec17e6b936c4d9eae3d74dbe482264991a',
 | 
			
		||||
      Proposal: '0xaf5fe5c3b0d9581ee88974bbc8699e6fa71efd1b321e44b2227103c9ef21dbdb'
 | 
			
		||||
    }[appName];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = Kernel;
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
const Base = require('./base');
 | 
			
		||||
 | 
			
		||||
class Registry extends Base {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = Registry;
 | 
			
		||||
@ -4,13 +4,19 @@ const RSVP = require('rsvp');
 | 
			
		||||
const Preflight = require('./utils/preflight');
 | 
			
		||||
 | 
			
		||||
const ABIS = {
 | 
			
		||||
  Contributors: require('./abis/Contributors.json'),
 | 
			
		||||
  Contributor: require('./abis/Contributor.json'),
 | 
			
		||||
  Contribution: require('./abis/Contribution.json'),
 | 
			
		||||
  Operator: require('./abis/Operator.json'),
 | 
			
		||||
  Registry: require('./abis/Registry.json'),
 | 
			
		||||
  Token: require('./abis/Token.json')
 | 
			
		||||
  Token: require('./abis/Token.json'),
 | 
			
		||||
  Proposal: require('./abis/Proposal.json'),
 | 
			
		||||
  Kernel: require('./abis/Kernel.json')
 | 
			
		||||
};
 | 
			
		||||
const RegistryAddress = require('./addresses/Registry.json');
 | 
			
		||||
const APP_CONTRACTS = [
 | 
			
		||||
  'Contributor',
 | 
			
		||||
  'Contribution',
 | 
			
		||||
  'Token',
 | 
			
		||||
  'Proposal'
 | 
			
		||||
];
 | 
			
		||||
const DaoAddresses = require('./addresses/dao.json');
 | 
			
		||||
 | 
			
		||||
const Contracts = require('./contracts');
 | 
			
		||||
const IPFS = require('./utils/ipfs')
 | 
			
		||||
@ -28,18 +34,18 @@ class Kredits {
 | 
			
		||||
 | 
			
		||||
    this.provider = provider;
 | 
			
		||||
    this.signer = signer;
 | 
			
		||||
    // by default we only need the registry address.
 | 
			
		||||
    // by default we only need the DAO/Kernel address.
 | 
			
		||||
    // the rest is loaded from there in the init() function
 | 
			
		||||
    this.addresses = addresses || { Registry: RegistryAddress[this.provider.chainId.toString()] }; // chainID must be a string
 | 
			
		||||
    this.addresses = addresses || { Kernel: DaoAddresses[this.provider.chainId.toString()] }; // chainID must be a string
 | 
			
		||||
    this.abis = abis || ABIS;
 | 
			
		||||
    this.ipfs = new IPFS(ipfsConfig);
 | 
			
		||||
    this.contracts = {};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  init(names) {
 | 
			
		||||
    let contractsToLoad = names || Object.keys(ABIS);
 | 
			
		||||
    let contractsToLoad = names || APP_CONTRACTS;
 | 
			
		||||
    let addressPromises = contractsToLoad.map((contractName) => {
 | 
			
		||||
      return this.Registry.functions.getProxyFor(contractName).then((address) => {
 | 
			
		||||
      return this.Kernel.getApp(contractName).then((address) => {
 | 
			
		||||
        this.addresses[contractName] = address;
 | 
			
		||||
      }).catch((error) => {
 | 
			
		||||
        throw new Error(`Failed to get address for ${contractName} from registry at ${this.Registry.contract.address}
 | 
			
		||||
@ -55,13 +61,13 @@ class Kredits {
 | 
			
		||||
    return new Kredits(provider, signer, { ipfsConfig: ipfsConfig }).init();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get Registry() {
 | 
			
		||||
    return this.contractFor('registry');
 | 
			
		||||
  get Kernel() {
 | 
			
		||||
    return this.contractFor('Kernel');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get Contributor() {
 | 
			
		||||
    // TODO: rename to contributor
 | 
			
		||||
    return this.contractFor('contributors');
 | 
			
		||||
    return this.contractFor('Contributor');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get Contributors() {
 | 
			
		||||
@ -69,16 +75,16 @@ class Kredits {
 | 
			
		||||
    return this.Contributor;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get Operator() {
 | 
			
		||||
    return this.contractFor('operator');
 | 
			
		||||
  get Proposal() {
 | 
			
		||||
    return this.contractFor('Proposal');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get Token() {
 | 
			
		||||
    return this.contractFor('token');
 | 
			
		||||
    return this.contractFor('Token');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get Contribution() {
 | 
			
		||||
    return this.contractFor('contribution');
 | 
			
		||||
    return this.contractFor('Contribution');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Should be private
 | 
			
		||||
 | 
			
		||||
@ -1,5 +0,0 @@
 | 
			
		||||
var Registry = artifacts.require('./upgradeable/Registry.sol');
 | 
			
		||||
 | 
			
		||||
module.exports = function(deployer) {
 | 
			
		||||
  deployer.deploy(Registry);
 | 
			
		||||
};
 | 
			
		||||
@ -1,15 +0,0 @@
 | 
			
		||||
var Registry = artifacts.require('./Registry.sol');
 | 
			
		||||
var Token = artifacts.require('./Token.sol');
 | 
			
		||||
 | 
			
		||||
module.exports = function(deployer) {
 | 
			
		||||
  deployer.deploy(Token).then(function(token) {
 | 
			
		||||
    console.log('Registry address: ', Registry.address);
 | 
			
		||||
    console.log('Token address: ', Token.address);
 | 
			
		||||
    Registry.deployed().then(function(registry) {
 | 
			
		||||
      registry.addVersion('Token', Token.address);
 | 
			
		||||
      registry.createProxy('Token', 1);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,13 +0,0 @@
 | 
			
		||||
var Registry = artifacts.require('./Registry.sol');
 | 
			
		||||
var Contributors = artifacts.require('./Contributors.sol');
 | 
			
		||||
 | 
			
		||||
module.exports = function(deployer) {
 | 
			
		||||
  deployer.deploy(Contributors).then(function(contributors) {
 | 
			
		||||
    console.log('Registry address: ', Registry.address);
 | 
			
		||||
    console.log('Contributors address: ', Contributors.address);
 | 
			
		||||
    Registry.deployed().then(function(registry) {
 | 
			
		||||
      registry.addVersion('Contributors', Contributors.address);
 | 
			
		||||
      registry.createProxy('Contributors', 1);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
@ -1,13 +0,0 @@
 | 
			
		||||
var Registry = artifacts.require('./Registry.sol');
 | 
			
		||||
var Operator = artifacts.require('./Operator.sol');
 | 
			
		||||
 | 
			
		||||
module.exports = function(deployer) {
 | 
			
		||||
  deployer.deploy(Operator).then(function(operator) {
 | 
			
		||||
    console.log('Registry address: ', Registry.address);
 | 
			
		||||
    console.log('Operator address: ', Operator.address);
 | 
			
		||||
    Registry.deployed().then(function(registry) {
 | 
			
		||||
      registry.addVersion('Operator', Operator.address);
 | 
			
		||||
      registry.createProxy('Operator', 1);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
@ -1,13 +0,0 @@
 | 
			
		||||
var Registry = artifacts.require('./Registry.sol');
 | 
			
		||||
var Contribution = artifacts.require('./Contribution.sol');
 | 
			
		||||
 | 
			
		||||
module.exports = function(deployer) {
 | 
			
		||||
  deployer.deploy(Contribution).then(function(contribution) {
 | 
			
		||||
    console.log('Registry address: ', Registry.address);
 | 
			
		||||
    console.log('Contribution address: ', Contribution.address);
 | 
			
		||||
    Registry.deployed().then(function(registry) {
 | 
			
		||||
      registry.addVersion('Contribution', Contribution.address);
 | 
			
		||||
      registry.createProxy('Contribution', 1);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										14329
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										14329
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										10
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								package.json
									
									
									
									
									
								
							@ -7,7 +7,7 @@
 | 
			
		||||
    "test": "test"
 | 
			
		||||
  },
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build-json": "truffle compile && node ./scripts/build-json.js",
 | 
			
		||||
    "build-json": "aragon contracts compile --all && node ./scripts/build-json.js",
 | 
			
		||||
    "reset": "truffle migrate --reset && npm run build-json",
 | 
			
		||||
    "bootstrap": "npm run reset && truffle exec scripts/seeds.js",
 | 
			
		||||
    "ganache": "ganache-cli -p 7545 -i 100 --db=./.ganache-db -m kredits",
 | 
			
		||||
@ -25,11 +25,13 @@
 | 
			
		||||
  },
 | 
			
		||||
  "homepage": "https://github.com/67P/truffle-kredits#readme",
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@aragon/cli": "^5.5.0",
 | 
			
		||||
    "@aragon/kits-base": "^1.0.0",
 | 
			
		||||
    "@aragon/os": "^4.1.0",
 | 
			
		||||
    "async-each-series": "^1.1.0",
 | 
			
		||||
    "ganache-cli": "^6.1.8",
 | 
			
		||||
    "openzeppelin-solidity": "^2.2.0",
 | 
			
		||||
    "promptly": "^3.0.3",
 | 
			
		||||
    "truffle": "^4.1.14",
 | 
			
		||||
    "zeppelin-solidity": "^1.7.0"
 | 
			
		||||
    "solc": "^0.4.25"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "ethers": "3.0.15",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										43
									
								
								scripts/add-contribution.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								scripts/add-contribution.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
			
		||||
const promptly = require('promptly');
 | 
			
		||||
 | 
			
		||||
const ethers = require('ethers');
 | 
			
		||||
const Kredits = require('../lib/kredits');
 | 
			
		||||
 | 
			
		||||
module.exports = async function(callback) {
 | 
			
		||||
  const networkId = parseInt(web3.version.network);
 | 
			
		||||
  const provider = new ethers.providers.Web3Provider(
 | 
			
		||||
    web3.currentProvider, { chainId: networkId }
 | 
			
		||||
  );
 | 
			
		||||
  const kredits = await new Kredits(provider, provider.getSigner()).init();
 | 
			
		||||
 | 
			
		||||
  console.log(`Using Contributions at: ${kredits.Contribution.contract.address}`);
 | 
			
		||||
 | 
			
		||||
  let contributor = await promptly.prompt('Contributor (address or id): ');
 | 
			
		||||
  let contributorId;
 | 
			
		||||
  if (contributor.length < 5) {
 | 
			
		||||
    contributorAccount = await kredits.Contributor.functions.getContributorAddressById(contributor);
 | 
			
		||||
  } else {
 | 
			
		||||
    contributorAccount = contributor;
 | 
			
		||||
  }
 | 
			
		||||
  console.log(`Creating a contribution for contributor Account #${contributorAccount}`);
 | 
			
		||||
 | 
			
		||||
  let contributionAttributes = {
 | 
			
		||||
    contributorAccount,
 | 
			
		||||
    amount: await promptly.prompt('Amount: '),
 | 
			
		||||
    description: await promptly.prompt('Description: '),
 | 
			
		||||
    kind: await promptly.prompt('Kind: ', { default: 'dev' }),
 | 
			
		||||
    url: await promptly.prompt('URL: ', { default: '' })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  console.log("\nAdding contribution:");
 | 
			
		||||
  console.log(contributionAttributes);
 | 
			
		||||
 | 
			
		||||
  kredits.Contribution.addContribution(contributionAttributes, { gasLimit: 300000 }).then((result) => {
 | 
			
		||||
    console.log("\n\nResult:");
 | 
			
		||||
    console.log(result);
 | 
			
		||||
    callback();
 | 
			
		||||
  }).catch((error) => {
 | 
			
		||||
    console.log('Failed to create contribution');
 | 
			
		||||
    callback(error);
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
@ -1,4 +1,3 @@
 | 
			
		||||
const Registry = artifacts.require('./Registry.sol');
 | 
			
		||||
const promptly = require('promptly');
 | 
			
		||||
 | 
			
		||||
const ethers = require('ethers');
 | 
			
		||||
@ -11,39 +10,35 @@ async function prompt(message, options) {
 | 
			
		||||
  return await promptly.prompt(message, options);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = function(callback) {
 | 
			
		||||
  Registry.deployed().then(async (registry) => {
 | 
			
		||||
module.exports = async function(callback) {
 | 
			
		||||
  const networkId = parseInt(web3.version.network);
 | 
			
		||||
  const provider = new ethers.providers.Web3Provider(
 | 
			
		||||
    web3.currentProvider, { chainId: networkId }
 | 
			
		||||
  );
 | 
			
		||||
  const kredits = await new Kredits(provider, provider.getSigner()).init();
 | 
			
		||||
 | 
			
		||||
    const networkId = parseInt(web3.version.network);
 | 
			
		||||
    const provider = new ethers.providers.Web3Provider(
 | 
			
		||||
      web3.currentProvider, { chainId: networkId }
 | 
			
		||||
    );
 | 
			
		||||
    const kredits = await Kredits.setup(provider, provider.getSigner());
 | 
			
		||||
  console.log(`Using contributors at: ${kredits.Contributor.contract.address}`);
 | 
			
		||||
 | 
			
		||||
    console.log(`Using contributors at: ${kredits.Contributor.contract.address}`);
 | 
			
		||||
  let contributorAttributes = {
 | 
			
		||||
    account: await prompt('Contributor address: ', {}),
 | 
			
		||||
    name: await prompt('Name: '),
 | 
			
		||||
    isCore: await prompt('core? y/n') === 'y',
 | 
			
		||||
    kind: await prompt('Kind (default person): ', {default: 'person'}),
 | 
			
		||||
    url: await prompt('URL: '),
 | 
			
		||||
    github_username: await prompt('GitHub username: '),
 | 
			
		||||
    github_uid: await prompt('GitHub UID: '),
 | 
			
		||||
    wiki_username: await prompt('Wiki username: '),
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
    let contributorAttributes = {
 | 
			
		||||
      account: await prompt('Contributor address: ', {}),
 | 
			
		||||
      name: await prompt('Name: '),
 | 
			
		||||
      isCore: await prompt('core? y/n') === 'y',
 | 
			
		||||
      kind: await prompt('Kind (default person): ', {default: 'person'}),
 | 
			
		||||
      url: await prompt('URL: '),
 | 
			
		||||
      github_username: await prompt('GitHub username: '),
 | 
			
		||||
      github_uid: await prompt('GitHub UID: '),
 | 
			
		||||
      wiki_username: await prompt('Wiki username: '),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    console.log("\nAdding contributor:");
 | 
			
		||||
    console.log(contributorAttributes);
 | 
			
		||||
 | 
			
		||||
    kredits.Contributor.add(contributorAttributes, { gasLimit: 250000 }).then((result) => {
 | 
			
		||||
      console.log("\n\nResult:");
 | 
			
		||||
      console.log(result);
 | 
			
		||||
      callback();
 | 
			
		||||
    }).catch((error) => {
 | 
			
		||||
      console.log('Failed to create contributor');
 | 
			
		||||
      callback(error);
 | 
			
		||||
    });
 | 
			
		||||
  console.log("\nAdding contributor:");
 | 
			
		||||
  console.log(contributorAttributes);
 | 
			
		||||
 | 
			
		||||
  kredits.Contributor.add(contributorAttributes, { gasLimit: 250000 }).then((result) => {
 | 
			
		||||
    console.log("\n\nResult:");
 | 
			
		||||
    console.log(result);
 | 
			
		||||
    callback();
 | 
			
		||||
  }).catch((error) => {
 | 
			
		||||
    console.log('Failed to create contributor');
 | 
			
		||||
    callback(error);
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,46 +1,43 @@
 | 
			
		||||
const Registry = artifacts.require('./Registry.sol');
 | 
			
		||||
const promptly = require('promptly');
 | 
			
		||||
 | 
			
		||||
const ethers = require('ethers');
 | 
			
		||||
const Kredits = require('../lib/kredits');
 | 
			
		||||
 | 
			
		||||
module.exports = function(callback) {
 | 
			
		||||
  Registry.deployed().then(async (registry) => {
 | 
			
		||||
    const networkId = parseInt(web3.version.network);
 | 
			
		||||
    const provider = new ethers.providers.Web3Provider(
 | 
			
		||||
      web3.currentProvider, { chainId: networkId }
 | 
			
		||||
    );
 | 
			
		||||
    const kredits = await Kredits.setup(provider, provider.getSigner());
 | 
			
		||||
module.exports = async function(callback) {
 | 
			
		||||
  const networkId = parseInt(web3.version.network);
 | 
			
		||||
  const provider = new ethers.providers.Web3Provider(
 | 
			
		||||
    web3.currentProvider, { chainId: networkId }
 | 
			
		||||
  );
 | 
			
		||||
  const kredits = await new Kredits(provider, provider.getSigner()).init();
 | 
			
		||||
 | 
			
		||||
    console.log(`Using operator at: ${kredits.Operator.contract.address}`);
 | 
			
		||||
  console.log(`Using Proposal at: ${kredits.Proposal.contract.address}`);
 | 
			
		||||
 | 
			
		||||
    let contributor = await promptly.prompt('Contributor (address or id): ');
 | 
			
		||||
    let contributorId;
 | 
			
		||||
    if (contributor.length < 5) {
 | 
			
		||||
      contributorId = contributor;
 | 
			
		||||
    } else {
 | 
			
		||||
      contributorId = await kredits.Contributor.functions.getContributorIdByAddress(contributor);
 | 
			
		||||
    }
 | 
			
		||||
    console.log(`Creating a proposal for contributor ID #${contributorId}`);
 | 
			
		||||
  let contributor = await promptly.prompt('Contributor (address or id): ');
 | 
			
		||||
  let contributorId;
 | 
			
		||||
  if (contributor.length < 5) {
 | 
			
		||||
    contributorId = contributor;
 | 
			
		||||
  } else {
 | 
			
		||||
    contributorId = await kredits.Contributor.functions.getContributorIdByAddress(contributor);
 | 
			
		||||
  }
 | 
			
		||||
  console.log(`Creating a proposal for contributor ID #${contributorId}`);
 | 
			
		||||
 | 
			
		||||
    let contributionAttributes = {
 | 
			
		||||
      contributorId,
 | 
			
		||||
      amount: await promptly.prompt('Amount: '),
 | 
			
		||||
      description: await promptly.prompt('Description: '),
 | 
			
		||||
      kind: await promptly.prompt('Kind: ', { default: 'dev' }),
 | 
			
		||||
      url: await promptly.prompt('URL: ', { default: '' })
 | 
			
		||||
    }
 | 
			
		||||
  let contributionAttributes = {
 | 
			
		||||
    contributorId,
 | 
			
		||||
    amount: await promptly.prompt('Amount: '),
 | 
			
		||||
    description: await promptly.prompt('Description: '),
 | 
			
		||||
    kind: await promptly.prompt('Kind: ', { default: 'dev' }),
 | 
			
		||||
    url: await promptly.prompt('URL: ', { default: '' })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    console.log("\nAdding proposal:");
 | 
			
		||||
    console.log(contributionAttributes);
 | 
			
		||||
  console.log("\nAdding proposal:");
 | 
			
		||||
  console.log(contributionAttributes);
 | 
			
		||||
 | 
			
		||||
    kredits.Operator.addProposal(contributionAttributes, { gasLimit: 300000 }).then((result) => {
 | 
			
		||||
      console.log("\n\nResult:");
 | 
			
		||||
      console.log(result);
 | 
			
		||||
      callback();
 | 
			
		||||
    }).catch((error) => {
 | 
			
		||||
      console.log('Failed to create proposal');
 | 
			
		||||
      console.log(error);
 | 
			
		||||
    });
 | 
			
		||||
  kredits.Proposal.addProposal(contributionAttributes, { gasLimit: 300000 }).then((result) => {
 | 
			
		||||
    console.log("\n\nResult:");
 | 
			
		||||
    console.log(result);
 | 
			
		||||
    callback();
 | 
			
		||||
  }).catch((error) => {
 | 
			
		||||
    console.log('Failed to create proposal');
 | 
			
		||||
    callback(error);
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,13 +4,12 @@ const path = require('path');
 | 
			
		||||
const contractsPath = path.join(__dirname, '..', 'build', 'contracts');
 | 
			
		||||
const libPath = path.join(__dirname, '..', 'lib');
 | 
			
		||||
const abisPath = path.join(libPath, 'abis');
 | 
			
		||||
const addressesPath = path.join(libPath, 'addresses');
 | 
			
		||||
 | 
			
		||||
const files = [
 | 
			
		||||
  'Contributors',
 | 
			
		||||
  'Contributor',
 | 
			
		||||
  'Contribution',
 | 
			
		||||
  'Operator',
 | 
			
		||||
  'Registry',
 | 
			
		||||
  'Kernel',
 | 
			
		||||
  'Proposal',
 | 
			
		||||
  'Token'
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@ -18,17 +17,6 @@ files.forEach((fileName) => {
 | 
			
		||||
  let file = require(`${contractsPath}/${fileName}.json`);
 | 
			
		||||
  let abiFile = path.join(abisPath, `${fileName}.json`);
 | 
			
		||||
  fs.writeFileSync(abiFile, JSON.stringify(file.abi));
 | 
			
		||||
 | 
			
		||||
  if (fileName === 'Registry') {
 | 
			
		||||
    let addresseFile = path.join(addressesPath, `${fileName}.json`);
 | 
			
		||||
    let content = fs.readFileSync(addresseFile);
 | 
			
		||||
    let addresses = Object.keys(file.networks)
 | 
			
		||||
      .reduce((addresses, key) => {
 | 
			
		||||
        addresses[key] = file.networks[key].address;
 | 
			
		||||
        return addresses;
 | 
			
		||||
      }, JSON.parse(content));
 | 
			
		||||
    fs.writeFileSync(addresseFile, JSON.stringify(addresses));
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
console.log("Don't forget to reaload the JSON files from your application; i.e. restart kredits-web");
 | 
			
		||||
 | 
			
		||||
@ -5,14 +5,12 @@ const ethers = require('ethers');
 | 
			
		||||
const Kredits = require('../lib/kredits');
 | 
			
		||||
 | 
			
		||||
module.exports = function(callback) {
 | 
			
		||||
  const Registry = artifacts.require('./Registry.sol');
 | 
			
		||||
  Registry.deployed().then(async (registry) => {
 | 
			
		||||
    const networkId = parseInt(web3.version.network);
 | 
			
		||||
    const provider = new ethers.providers.Web3Provider(
 | 
			
		||||
      web3.currentProvider, { chainId: networkId }
 | 
			
		||||
    );
 | 
			
		||||
    const kredits = await Kredits.setup(provider, provider.getSigner());
 | 
			
		||||
  const networkId = parseInt(web3.version.network);
 | 
			
		||||
  const provider = new ethers.providers.Web3Provider(
 | 
			
		||||
    web3.currentProvider, { chainId: networkId }
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  new Kredits(provider, provider.getSigner()).init().then(async function(kredits) {
 | 
			
		||||
    let contractName = await promptly.prompt('Contract Name: ');
 | 
			
		||||
    const contractWrapper = kredits[contractName];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										49
									
								
								scripts/deploy-kit.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								scripts/deploy-kit.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
			
		||||
const deployDAOFactory = require('@aragon/os/scripts/deploy-daofactory.js')
 | 
			
		||||
const KreditsKit = artifacts.require('KreditsKit')
 | 
			
		||||
 | 
			
		||||
const fs = require('fs');
 | 
			
		||||
const path = require('path');
 | 
			
		||||
const libPath = path.join(__dirname, '..', 'lib');
 | 
			
		||||
const addressesPath = path.join(libPath, 'addresses');
 | 
			
		||||
 | 
			
		||||
const ensAddr = process.env.ENS
 | 
			
		||||
 | 
			
		||||
module.exports = async (callback) => {
 | 
			
		||||
  if (!ensAddr) {
 | 
			
		||||
    callback(new Error("ENS address not found in environment variable ENS"))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  deployDAOFactory(null, { artifacts, verbose: false })
 | 
			
		||||
    .catch(console.log)
 | 
			
		||||
    .then((result) => {
 | 
			
		||||
      const daoFactory = result.daoFactory
 | 
			
		||||
 | 
			
		||||
      KreditsKit.new(daoFactory.address, ensAddr)
 | 
			
		||||
        .catch(console.log)
 | 
			
		||||
        .then((kreditsKit) => {
 | 
			
		||||
          console.log(kreditsKit.address)
 | 
			
		||||
 | 
			
		||||
          kreditsKit.newInstance().then((ret) => {
 | 
			
		||||
          console.log(ret.logs);
 | 
			
		||||
          const installedEvents = ret.logs.filter(log => log.event === 'InstalledApp').map(log => log.args)
 | 
			
		||||
          const deployEvents = ret.logs.filter(log => log.event === 'DeployInstance').map(log => log.args)
 | 
			
		||||
 | 
			
		||||
          if (deployEvents.length > 1) {
 | 
			
		||||
            callback(new Error("More than one DAO was deployed. Something is wrong"))
 | 
			
		||||
          }
 | 
			
		||||
          const daoAddress = deployEvents[0].dao;
 | 
			
		||||
          const networkId = parseInt(web3.version.network);
 | 
			
		||||
 | 
			
		||||
          let addresseFile = path.join(addressesPath, `dao.json`);
 | 
			
		||||
          let addresses = JSON.parse(fs.readFileSync(addresseFile));
 | 
			
		||||
 | 
			
		||||
          addresses[networkId] = daoAddress;
 | 
			
		||||
          fs.writeFileSync(addresseFile, JSON.stringify(addresses));
 | 
			
		||||
 | 
			
		||||
          callback();
 | 
			
		||||
        }).catch((e) => {
 | 
			
		||||
          console.log(e);
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
@ -1,18 +1,16 @@
 | 
			
		||||
const REPL = require('repl');
 | 
			
		||||
const promptly = require('promptly');
 | 
			
		||||
 | 
			
		||||
const ethers = require('ethers');
 | 
			
		||||
const Kredits = require('../lib/kredits');
 | 
			
		||||
 | 
			
		||||
module.exports = function(callback) {
 | 
			
		||||
  const Registry = artifacts.require('./Registry.sol');
 | 
			
		||||
  Registry.deployed().then(async (registry) => {
 | 
			
		||||
    const networkId = parseInt(web3.version.network);
 | 
			
		||||
    const provider = new ethers.providers.Web3Provider(
 | 
			
		||||
      web3.currentProvider, { chainId: networkId }
 | 
			
		||||
    );
 | 
			
		||||
    const kredits = await Kredits.setup(provider, provider.getSigner());
 | 
			
		||||
    console.log(`defined variables: kredits, web3`);
 | 
			
		||||
  const networkId = parseInt(web3.version.network);
 | 
			
		||||
  const provider = new ethers.providers.Web3Provider(
 | 
			
		||||
    web3.currentProvider, { chainId: networkId }
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  new Kredits(provider, provider.getSigner()).init().then((kredits) => {
 | 
			
		||||
    console.log(`Defined variables: kredits, web3`);
 | 
			
		||||
    let r = REPL.start();
 | 
			
		||||
    r.context.kredits = kredits;
 | 
			
		||||
    r.context.web3 = web3;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										73
									
								
								truffle.js
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								truffle.js
									
									
									
									
									
								
							@ -1,15 +1,68 @@
 | 
			
		||||
/**
 | 
			
		||||
 * https://github.com/aragon/aragonOS/blob/v4.0.0/truffle-config.js
 | 
			
		||||
 */
 | 
			
		||||
const homedir = require('homedir')
 | 
			
		||||
const path = require('path')
 | 
			
		||||
 | 
			
		||||
const HDWalletProvider = require('truffle-hdwallet-provider')
 | 
			
		||||
const HDWalletProviderPrivkey = require('truffle-hdwallet-provider-privkey')
 | 
			
		||||
 | 
			
		||||
const DEFAULT_MNEMONIC = 'explain tackle mirror kit van hammer degree position ginger unfair soup bonus'
 | 
			
		||||
 | 
			
		||||
const defaultRPC = (network) =>
 | 
			
		||||
  `https://${network}.infura.io`
 | 
			
		||||
 | 
			
		||||
const configFilePath = (filename) =>
 | 
			
		||||
  path.join(homedir(), `.aragon/${filename}`)
 | 
			
		||||
 | 
			
		||||
const mnemonic = () => {
 | 
			
		||||
  try {
 | 
			
		||||
    return require(configFilePath('mnemonic.json')).mnemonic
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    return DEFAULT_MNEMONIC
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const settingsForNetwork = (network) => {
 | 
			
		||||
  try {
 | 
			
		||||
    return require(configFilePath(`${network}_key.json`))
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    return { }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Lazily loaded provider
 | 
			
		||||
const providerForNetwork = (network) => (
 | 
			
		||||
  () => {
 | 
			
		||||
    let { rpc, keys } = settingsForNetwork(network)
 | 
			
		||||
    rpc = rpc || defaultRPC(network)
 | 
			
		||||
 | 
			
		||||
    if (!keys || keys.length == 0) {
 | 
			
		||||
      return new HDWalletProvider(mnemonic(), rpc)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return new HDWalletProviderPrivkey(keys, rpc)
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
module.exports = {
 | 
			
		||||
  // See <http://truffleframework.com/docs/advanced/configuration>
 | 
			
		||||
  networks: {
 | 
			
		||||
    development: {
 | 
			
		||||
      host: "127.0.0.1",
 | 
			
		||||
      port: 7545,
 | 
			
		||||
      network_id: "*" // Match any network id
 | 
			
		||||
    },
 | 
			
		||||
    kovan: {
 | 
			
		||||
      host: "127.0.0.1",
 | 
			
		||||
    rpc: {
 | 
			
		||||
      host: 'localhost',
 | 
			
		||||
      port: 8545,
 | 
			
		||||
      network_id: "42"
 | 
			
		||||
      network_id: '*'
 | 
			
		||||
    },
 | 
			
		||||
    development: {
 | 
			
		||||
      host: 'localhost',
 | 
			
		||||
      port: 8545,
 | 
			
		||||
      network_id: '*'
 | 
			
		||||
    },
 | 
			
		||||
    mainnet: {
 | 
			
		||||
      network_id: 1,
 | 
			
		||||
      provider: providerForNetwork('mainnet')
 | 
			
		||||
    },
 | 
			
		||||
    rinkeby: {
 | 
			
		||||
      network_id: 4,
 | 
			
		||||
      provider: providerForNetwork('rinkeby')
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user