This repository has been archived by the owner on Apr 29, 2019. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit ae10d77
Showing
28 changed files
with
2,099 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Dependency directory | ||
node_modules | ||
|
||
# Generated files | ||
build | ||
environments | ||
|
||
# IDE | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2017 Alice Ltd. (Jakub Wojciechowski jakub@alice.si) | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# Alice Smart Contracts | ||
|
||
This project is a collection of smart contracts that are used by <https://alice.si>. | ||
|
||
### Overview | ||
|
||
Smart contracts implement a Pay for success donation model. After a donor sends money to the campaign, a corresponding amount of Alice Tokens are being generated and credited to the Charity contract. Tokens are held in an escrow and are released only if a dedicated Validator confirms that the expected outcome has been achieved. Tokens are moved to the Beneficiary account after the validation is performed. Any outstanding tokens may be returned to donors and reused for future donations. | ||
|
||
### Installation | ||
This project requires [node-js](https://github.com/nodejs/node) runtime and uses [truffle](https://github.com/trufflesuite/truffle) Ethereum smart contracts development framework. In order to run it, install truffle first: | ||
|
||
npm install -g truffle | ||
|
||
Then install all of the node-js dependencies | ||
|
||
npm install | ||
|
||
Connection to blockchain node is defined in truffle.js: | ||
|
||
networks: { | ||
dev: { | ||
network_id: "*", | ||
gas: 4000000, | ||
host: 'localhost', | ||
port: '8545' | ||
} | ||
} | ||
|
||
We recommend using popular Ethereum test client [testrpc](https://github.com/ethereumjs/testrpc) as a default node: | ||
|
||
npm install -g ethereumjs-testrpc | ||
|
||
### Running tests | ||
|
||
To run all of the smart contract tests use following truffle command in your console: | ||
|
||
truffle test --network dev | ||
|
||
If you are using testrpc client remember to start it with sufficient number of test accounts: | ||
|
||
testrpc -a 100 | ||
|
||
### Demo dApp | ||
|
||
We created a demo dApp so you can interact and test smart contract in a visual environment rather than hacking console scripts. To run this mode please deploy the smart contracts to your blockchain network: | ||
|
||
truffle migrate --network dev | ||
|
||
... and then launch a demo server: | ||
|
||
truffle serve | ||
|
||
This demo dApp should be available at: http://localhost:8080/ a look like that: | ||
![screenshot](https://s3.eu-west-2.amazonaws.com/alice-res/alice-dApp.png) | ||
|
||
## Contributions | ||
|
||
All comments, ideas for improvements and pull requests are welcomed. We want to improve the project based on feedback from the community. | ||
|
||
## License | ||
|
||
MIT License | ||
|
||
Copyright (c) 2017 Alice Ltd. (Jakub Wojciechowski jakub@alice.si) | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>Alice</title> | ||
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'> | ||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel='stylesheet' type='text/css'> | ||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css"> | ||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"> | ||
<link href="./app.css" rel='stylesheet' type='text/css'> | ||
<script src="//code.jquery.com/jquery-1.10.2.min.js"></script> | ||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> | ||
<script src="./app.js"></script> | ||
</head> | ||
<body> | ||
<section class="content-header"> | ||
<h1> | ||
Alice | ||
<small>Smart Contracts Demo</small> | ||
</h1> | ||
</section> | ||
|
||
<div class="row"> | ||
<div class="col-lg-3 col-xs-6"> | ||
<!-- small box --> | ||
<div class="small-box bg-aqua"> | ||
<div class="inner" style="height: 128px"> | ||
<h3>Donor 1</h3> | ||
<p><i class="fa fa-database"></i> <span id="balance_donor_1"></span> LHC</p> | ||
</div> | ||
<div class="icon"> | ||
<i class="ion ion-person"></i> | ||
</div> | ||
<a href="#" class="small-box-footer" onclick="donate(donor1Account, 20)">Donate (20) <i class="fa fa-arrow-circle-right"></i></a> | ||
<a href="#" class="small-box-footer" onclick="reuseUnspent(donor1Account)">Reuse Unspent <i class="fa fa-arrow-circle-right"></i></a> | ||
</div> | ||
|
||
<div class="small-box bg-aqua"> | ||
<div class="inner" style="height: 128px"> | ||
<h3>Donor 2</h3> | ||
<p><i class="fa fa-database"></i> <span id="balance_donor_2"></span> LHC</p> | ||
</div> | ||
<div class="icon"> | ||
<i class="ion ion-person"></i> | ||
</div> | ||
<a href="#" class="small-box-footer" onclick="donate(donor2Account, 20)">Donate (20) <i class="fa fa-arrow-circle-right"></i></a> | ||
<a href="#" class="small-box-footer" onclick="reuseUnspent(donor2Account)">Reuse Unspent <i class="fa fa-arrow-circle-right"></i></a> | ||
</div> | ||
|
||
</div> | ||
|
||
<!-- ./col --> | ||
<div class="col-lg-3 col-xs-6"> | ||
<!-- small box --> | ||
<div class="small-box bg-yellow"> | ||
<div class="inner" style="height: 355px"> | ||
<h3>Contract</h3> | ||
<p><i class="fa fa-databas"></i> <span id="balance_charity"></span> LHC</p> | ||
<p><i class="fa fa-databas"></i> <span id="accounts"></span> unspent accounts</p> | ||
<div style="font-style: italic; text-align: center; padding-top: 20px"> | ||
Smart contract. Works as an escrow keeping donations before an outcome payment is authorized. | ||
</div> | ||
</div> | ||
<div class="icon"> | ||
<i class="ion ion-ios-list-outline"></i> | ||
</div> | ||
<a href="#" class="small-box-footer" onclick="payBackAll()"><i class="fa fa-arrow-circle-left"></i> Pay back</a> | ||
</div> | ||
</div> | ||
<!-- ./col --> | ||
<div class="col-lg-3 col-xs-6"> | ||
<!-- small box --> | ||
<div class="small-box bg-red"> | ||
<div class="inner" style="height: 330px"> | ||
<h3>Judge</h3> | ||
|
||
<p>External validator</p> | ||
|
||
<div style="font-style: italic; text-align: center; padding-top: 20px"> | ||
Trusted organization (e.g. government agency) which authorize outcome payments. | ||
</div> | ||
</div> | ||
<div class="icon"> | ||
<i class="ion ion-android-checkbox-outline"></i> | ||
</div> | ||
<a href="#" class="small-box-footer" onclick="validateOutcome('Tenancy', 200)">Tenancy agreement (200) <i class="fa fa-arrow-circle-right"></i></a> | ||
<a href="#" class="small-box-footer" onclick="validateOutcome('Employment', 100)">Employment contract (100) <i class="fa fa-arrow-circle-right"></i></a> | ||
</div> | ||
</div> | ||
<div class="col-lg-3 col-xs-6"> | ||
<!-- small box --> | ||
<div class="small-box bg-green"> | ||
<div class="inner" style="height: 383px"> | ||
<h3>Beneficiary</h3> | ||
|
||
<p><i class="fa fa-database"></i> <span id="balance_beneficiary"></span> LHC</p> | ||
|
||
<div style="font-style: italic; text-align: center; padding-top: 20px"> | ||
Charity organization which use the money to provide help for homeless people. | ||
</div> | ||
|
||
</div> | ||
<div class="icon"> | ||
<i class="ion ion-ios-people-outline"></i> | ||
</div> | ||
</div> | ||
</div> | ||
<!-- ./col --> | ||
</div> | ||
|
||
<div class="box box-primary" style="background-color: #F0F0F0; border-color: #ddd"> | ||
<div class="box-header with-border" style="border-bottom: 1px solid #ddd;"> | ||
<h3 class="box-title">Blockchain logs</h3> | ||
</div> | ||
<!-- /.box-header --> | ||
<div class="box-body" id="log"> | ||
|
||
</div> | ||
<!-- /.box-body --> | ||
</div> | ||
|
||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
var accounts; | ||
var aliceAccount; | ||
var donor1Account; | ||
var donor2Account; | ||
var beneficiaryAccount; | ||
var judgeAccount; | ||
|
||
var TokenContract; | ||
var CharityContract; | ||
var ImpactContract; | ||
|
||
var balances = {}; | ||
|
||
function refreshBalance() { | ||
showBalance(donor1Account, "balance_donor_1"); | ||
showBalance(donor2Account, "balance_donor_2"); | ||
showBalance(CharityContract.address, "balance_charity"); | ||
showBalance(beneficiaryAccount, "balance_beneficiary"); | ||
} | ||
|
||
function showBalance(account, element) { | ||
TokenContract.balanceOf(account).then(function(value) { | ||
var balance_element = document.getElementById(element); | ||
balance_element.innerHTML = value.valueOf(); | ||
balances[account] = value; | ||
}); | ||
} | ||
|
||
function showAllImpacts() { | ||
showImpact('Tenancy'); | ||
showImpact('Employment'); | ||
} | ||
|
||
function showImpact(name) { | ||
ImpactContract.getImpactCount.call(name).then(function(c) { | ||
var count = c.valueOf(); | ||
console.log(name + ' impact: ' + count); | ||
for(var i=0; i < count; i++) { | ||
(function(index) { | ||
ImpactContract.getImpactDonor.call(name, i).then(function (address) { | ||
console.log(name + ' address[' + index + ']: ' + address); | ||
ImpactContract.getImpactValue.call(name, address).then(function (value) { | ||
console.log(name + ' value[' + index + ']: ' + value); | ||
}); | ||
}); | ||
})(i); | ||
} | ||
}); | ||
} | ||
|
||
function donate(account, value) { | ||
TokenContract.mint(CharityContract.address, value, {from: aliceAccount, gas: 1000000}).then(function(tx) { | ||
return CharityContract.notify(account, value, {from: aliceAccount, gas: 1000000}) | ||
.then(function () { | ||
refreshBalance(); | ||
return null; | ||
}); | ||
}) | ||
} | ||
|
||
function reuseUnspent(account) { | ||
TokenContract.transfer(CharityContract.address, balances[account], {from: account, gas: 1000000}) | ||
.then(function(tx) { | ||
return CharityContract.notify(account, balances[account], {from: aliceAccount, gas: 1000000}) | ||
.then(function () { | ||
console.log("Donated remaining funds: " + balances[account]); | ||
refreshBalance(); | ||
return null; | ||
}); | ||
}); | ||
} | ||
|
||
function validateOutcome(name, value) { | ||
return CharityContract.unlockOutcome(name, value, {from: judgeAccount, gas: 500000}).then(function() { | ||
console.log("Validating outcome: " + name + " valued at: " + value); | ||
refreshBalance(); | ||
showAllImpacts(); | ||
return linkImpact(name, value); | ||
}); | ||
} | ||
|
||
function payBackAll() { | ||
payBack(donor1Account); | ||
payBack(donor2Account); | ||
} | ||
|
||
function payBack(account) { | ||
CharityContract.payBack(account, {from: aliceAccount, gas: 1000000}).then(function() { | ||
console.log("Payback done"); | ||
refreshBalance(); | ||
return null; | ||
}); | ||
} | ||
|
||
function linkImpact(name, outcomeValue) { | ||
return ImpactContract.getImpactLinked.call(name, {from: aliceAccount}).then(function(val) { | ||
console.log("Linked: " + val + " of: " + outcomeValue); | ||
if (val < outcomeValue) { | ||
console.log("Linking impact: " + val + " of: " + outcomeValue); | ||
return ImpactContract.linkImpact(name, {from: aliceAccount, gas: 2000000}).then(function(tx) { | ||
return linkImpact(name, outcomeValue); | ||
}); | ||
} | ||
}); | ||
} | ||
|
||
function mapAccounts(accounts) { | ||
aliceAccount = accounts[0]; | ||
judgeAccount = accounts[1]; | ||
beneficiaryAccount = accounts[2]; | ||
donor1Account = accounts[3]; | ||
donor2Account = accounts[4]; | ||
} | ||
|
||
function setupWeb3Filter() { | ||
var filter = web3.eth.filter({}); | ||
|
||
filter.watch(function (error, log) { | ||
console.log(log); | ||
var logBox = document.getElementById("log"); | ||
logBox.innerHTML += "Transaction hash: " + log.transactionHash + "<br/>"; | ||
}); | ||
} | ||
|
||
window.onload = function() { | ||
AliceToken.deployed() | ||
.then(function (instance) { | ||
TokenContract = instance; | ||
console.log(TokenContract); | ||
return Charity.deployed(); | ||
}).then(function(instance) { | ||
CharityContract = instance; | ||
return ImpactRegistry.deployed(); | ||
}).then(function(instance) { | ||
ImpactContract = instance; | ||
web3.eth.getAccounts(function(err, accs) { | ||
if (err != null) { | ||
alert("There was an error fetching your accounts."); | ||
return; | ||
} | ||
|
||
if (accs.length == 0) { | ||
alert("Couldn't get any accounts! Make sure your Ethereum client is configured correctly."); | ||
return; | ||
} | ||
|
||
mapAccounts(accs); | ||
refreshBalance(); | ||
}); | ||
}); | ||
|
||
setupWeb3Filter(); | ||
|
||
} |
Oops, something went wrong.