Skip to content

Commit

Permalink
Add prototype code
Browse files Browse the repository at this point in the history
  • Loading branch information
cc7768 authored and mrice32 committed Oct 11, 2018
1 parent d7678af commit 4d092fb
Show file tree
Hide file tree
Showing 18 changed files with 1,562 additions and 277 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/*

11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,14 @@ Contains some code for a first pass at a derivatives contract
https://medium.com/@olxc/ethereum-and-smart-contracts-basics-e5c84838b19

http://solidity.readthedocs.io/en/develop/index.html

https://karl.tech/learning-solidity-part-2-voting/

Read article below (and other things by Alex Evans):

https://medium.com/blockchannel/a-crash-course-in-mechanism-design-for-cryptoeconomic-applications-a9f06ab6a976

https://blockgeeks.com/guides/proof-of-work-vs-proof-of-stake/
https://cryptologie.net/article/424/writing-a-dapp-for-the-ethereum-block-chain/
https://medium.com/@mvmurthy/full-stack-hello-world-voting-ethereum-dapp-tutorial-part-1-40d2d0d807c2
https://electronjs.org/docs/tutorial/first-app
21 changes: 21 additions & 0 deletions app/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<title>Vote Coin</title>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
<script src="./app.js"></script>
</head>
<body>
<h1>US to ETH</h1>
<p>The current ETH to USD conversion is listed at <span id="price"></span></p>

<br>
<h1>Vote</h1>
<br><br><button id="send" onclick="App.voteYes()">This is correct</button>
<br><br><button id="send" onclick="App.voteNo()">This is incorrect</button>
<br><br>
<span id="status"></span>
<br>
<span class="hint"><strong>Hint:</strong> open the browser developer console to view any errors and warnings.</span>
</body>
</html>
121 changes: 121 additions & 0 deletions app/scripts/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Import the page's CSS. Webpack will know what to do with it.
import '../styles/app.css'

// Import libraries we need.
import {
default as Web3
} from 'web3'
import {
default as contract
} from 'truffle-contract'

// Import our contract artifacts and turn them into usable abstractions.
import voteCoinArtifact from '../../build/contracts/VoteCoin.json'

// MetaCoin is our usable abstraction, which we'll use through the code below.
const VoteCoin = contract(voteCoinArtifact)

// The following code is simple to show off interacting with your contracts.
// As your needs grow you will likely need to change its form and structure.
// For application bootstrapping, check out window.addEventListener below.
let accounts
let account

const App = {
start: function() {
const self = this
// Bootstrap the MetaCoin abstraction for Use.
VoteCoin.setProvider(web3.currentProvider)

// Get the initial account balance so it can be displayed.
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
}

accounts = accs
account = accounts[0]

self.fetchPrice()
// Also need call to function that updates prices on page here
})
},

setStatus: function(message) {
const status = document.getElementById('status')
status.innerHTML = message
},

fetchPrice: function() {
VoteCoin.deployed().then(function(instance) {
return instance.ETHUSD.call()
}).then(function(value) {
const balanceElement = document.getElementById('price')
balanceElement.innerHTML = value
console.log("We have a new price!", value)
}).catch(function(e) {
console.log(e)
this.setStatus('Error getting balance; see log.')
})
},

voteYes: function() {
VoteCoin.deployed().then(function(instance) {
return instance.currVoteId.call()
}).then(function(value) {return value.toNumber()}).then(function(voteId) {
VoteCoin.deployed().then(function(instance) {
instance.vote(voteId, 1, {from: account})
})
}).catch(function(e) {
console.log(e)
})
},

voteNo: function() {
VoteCoin.deployed().then(function(instance) {
return instance.currVoteId.call()
}).then(function(value) {return value.toNumber()}).then(function(voteId) {
VoteCoin.deployed().then(function(instance) {
instance.vote(voteId, 0, {from: account})
})
}).catch(function(e) {
console.log(e)
})
},

}

window.App = App

window.addEventListener('load', function() {
// Checking if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined') {
console.warn(
'Using web3 detected from external source.' +
' If you find that your accounts don\'t appear or you have 0 MetaCoin,' +
' ensure you\'ve configured that source properly.' +
' If using MetaMask, see the following link.' +
' Feel free to delete this warning. :)' +
' http://truffleframework.com/tutorials/truffle-and-metamask'
)
// Use Mist/MetaMask's provider
window.web3 = new Web3(web3.currentProvider)
} else {
console.warn(
'No web3 detected. Falling back to http://127.0.0.1:9545.' +
' You should remove this fallback when you deploy live, as it\'s inherently insecure.' +
' Consider switching to Metamask for development.' +
' More info here: http://truffleframework.com/tutorials/truffle-and-metamask'
)
// fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
window.web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:9545'))
}

App.start()
})
Empty file added app/styles/app.css
Empty file.
136 changes: 72 additions & 64 deletions contracts/Derivative.sol
Original file line number Diff line number Diff line change
@@ -1,124 +1,135 @@
/*
Derivative implementation
Implements a simplified version of ETH/USD derivatives.
TODO: Implement tax function
*/
pragma solidity ^0.4.22;

import "github.com/oraclize/ethereum-api/oraclizeAPI.sol";
import "installed_contracts/oraclize-api/contracts/usingOraclize.sol";


// This interface allows us to get the Ethereum-USD exchange rate
contract OracleInterface {
contract VoteCoinInterface {
string public ETHUSD;
}


contract Derivative {
// Financial information
mapping(address => int256) public balances; // Stored in Wei
int256 public default_penalty; //
int256 public required_margin; //
int256 public defaultPenalty; //
int256 public requiredMargin; //

// Contract states
address owner_address; // should this be public?
address counterparty_address; //
address ownerAddress; // should this be public?
address counterpartyAddress; //
bool public defaulted = false;
bool public terminated = false;
uint public start_time;
uint public end_time;
uint public startTime;
uint public endTime;

VoteCoinInterface oracle;
address oracleAddress;
int256 npv; // Net present value is measured in Wei

function Constructor(
address _counterparty_address,
uint _start_time,
uint _end_time,
int256 _default_penalty,
int256 _required_margin
constructor(
address _counterpartyAddress,
address _oracleAddress,
uint _startTime,
uint _endTime,
int256 _defaultPenalty,
int256 _requiredMargin
) public {

// Contract states
start_time = _start_time;
end_time = _end_time;
default_penalty = _default_penalty;
required_margin = _required_margin;
startTime = _startTime;
endTime = _endTime;
defaultPenalty = _defaultPenalty;
requiredMargin = _requiredMargin;
npv = 0;

// Address information
owner_address = msg.sender;
counterparty_address = _counterparty_address;
balances[owner_address] = 0;
balances[counterparty_address] = 0;
ownerAddress = msg.sender;
oracleAddress = _oracleAddress;
counterpartyAddress = _counterpartyAddress;
balances[ownerAddress] = 0;
balances[counterpartyAddress] = 0;
}

function update_balances(int256 npv_new) internal {
function updateBalances(int256 npvNew) internal {
// Compute difference -- Add the difference to owner and subtract
// from counterparty. Then update npv state variable
int256 npv_diff = npv - npv_new;
npv = npv_new;
int256 npvDiff = npv - npvNew;
npv = npvNew;

balances[owner_address] += npv_diff;
balances[counterparty_address] -= npv_diff;
balances[ownerAddress] += npvDiff;
balances[counterpartyAddress] -= npvDiff;
}

function is_default(address party_i) constant public returns (bool) {
return balances[party_i] < required_margin;
function isDefault(address party) constant public returns (bool) {
return balances[party] < requiredMargin;
}

function who_defaults()
function whoDefaults()
constant
public
returns (bool in_default, address defaulter, address not_defaulter)
returns (bool inDefault, address defaulter, address notDefaulter)
{
in_default = false;
inDefault = false;

if (is_default(owner_address)) {
defaulter = owner_address;
not_defaulter = counterparty_address;
in_default = true;
if (isDefault(ownerAddress)) {
defaulter = ownerAddress;
notDefaulter = counterpartyAddress;
inDefault = true;
}
else if (is_default(counterparty_address)) {
defaulter = counterparty_address;
not_defaulter = owner_address;
in_default = true;
else if (isDefault(counterpartyAddress)) {
defaulter = counterpartyAddress;
notDefaulter = ownerAddress;
inDefault = true;
}

return (in_default, defaulter, not_defaulter);
return (inDefault, defaulter, notDefaulter);
}

function is_terminated(uint time) constant public returns (bool ttt){
ttt = terminated || time > end_time;
function isTerminated(uint time) constant public returns (bool ttt){
ttt = terminated || time > endTime;
}

// Concrete contracts should inherit from this contract and then should only
// need to implement a `compute_npv` function. This allows for generic
// choices of npv functions
function compute_npv() public returns (int256 value);
function computeNpv() public returns (int256 value);

function remargin() external {
// Check if time is over...
// TODO: Ensure that the contract is remargined at the time that the
// contract ends
uint current_time = now;
if (current_time > end_time) {
uint currentTime = now;
if (currentTime > endTime) {
terminated = true;
}

// Update npv of contract
int256 npv_new = compute_npv();
update_balances(npv_new);
int256 npvNew = computeNpv();
updateBalances(npvNew);

// Check for default
bool in_default;
bool inDefault;
address defaulter;
address not_defaulter;
(in_default, defaulter, not_defaulter) = who_defaults();
address notDefaulter;
(inDefault, defaulter, notDefaulter) = whoDefaults();

// Check whether goes into default
if (in_default) {
if (inDefault) {
int256 penalty;
penalty = (balances[defaulter] < default_penalty) ?
penalty = (balances[defaulter] < defaultPenalty) ?
balances[defaulter] :
default_penalty;
defaultPenalty;

balances[defaulter] -= penalty;
balances[not_defaulter] += penalty;
balances[notDefaulter] += penalty;
defaulted = true;
terminated = true;
}
Expand All @@ -133,13 +144,13 @@ contract Derivative {
// If the contract has been defaulted on or terminated then can withdraw
// up to full balance -- If not then they are required to leave at least
// `required_margin` in the account
int256 withdrawable_amount = (defaulted || terminated) ?
int256 withdrawableAmount = (defaulted || terminated) ?
balances[msg.sender] :
balances[msg.sender] - required_margin;
balances[msg.sender] - requiredMargin;

// Can only withdraw the allowed amount
require(
(int256(withdrawable_amount) > int256(amount)),
(int256(withdrawableAmount) > int256(amount)),
"Attempting to withdraw more than allowed"
);

Expand All @@ -155,14 +166,11 @@ contract Derivative {
}


contract Derivative_ConstantNPV is Derivative, usingOraclize {

contract Derivative_ConstantNPV is usingOraclize, Derivative {

OracleInterface oracle;
address oracleAddress = 0x739De5b0fa95F40664CbdfC5D350e0c43B66f72e;

function compute_npv() public returns (int256 value) {
oracle = OracleInterface(oracleAddress);
function computeNpv() public returns (int256 value) {
oracle = VoteCoinInterface(oracleAddress);
string memory p = oracle.ETHUSD();
int256 price = int256(parseInt(p, 2));

Expand Down
Loading

0 comments on commit 4d092fb

Please sign in to comment.