Commit b08b0204 authored by chriseth's avatar chriseth

Merge pull request #7 from d11e9/usability

Usability features and UI polish
parents 1d460e89 8b1eca91
var multi = function(func) { return func.toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1]; }
var BALLOT_EXAMPLE = multi(function(){/*contract Ballot {
struct Voter {
uint weight;
bool voted;
uint8 vote;
address delegate;
}
struct Proposal {
uint voteCount;
}
address chairperson;
mapping(address => Voter) voters;
Proposal[] proposals;
// Create a new ballot with $(_numProposals) different proposals.
function Ballot(uint8 _numProposals) {
chairperson = msg.sender;
voters[chairperson].weight = 1;
proposals.length = _numProposals;
}
// Give $(voter) the right to vote on this ballot.
// May only be called by $(chairperson).
function giveRightToVote(address voter) {
if (msg.sender != chairperson || voters[voter].voted) return;
voters[voter].weight = 1;
}
// Delegate your vote to the voter $(to).
function delegate(address to) {
Voter sender = voters[msg.sender]; // assigns reference
if (sender.voted) return;
while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender)
to = voters[to].delegate;
if (to == msg.sender) return;
sender.voted = true;
sender.delegate = to;
Voter delegate = voters[to];
if (delegate.voted)
proposals[delegate.vote].voteCount += sender.weight;
else
delegate.weight += sender.weight;
}
// Give a single vote to proposal $(proposal).
function vote(uint8 proposal) {
Voter sender = voters[msg.sender];
if (sender.voted || proposal >= proposals.length) return;
sender.voted = true;
sender.vote = proposal;
proposals[proposal].voteCount += sender.weight;
}
function winningProposal() constant returns (uint8 winningProposal) {
uint256 winningVoteCount = 0;
for (uint8 proposal = 0; proposal < proposals.length; proposal++) {
if (proposals[proposal].voteCount > winningVoteCount) {
winningVoteCount = proposals[proposal].voteCount;
winningProposal = proposal;
}
++proposal;
}
}
}
*/});
\ No newline at end of file
......@@ -12,67 +12,206 @@ body {
font-size: 12px;
color: #111111;
}
#solIcon {
right: 10px;
top: 10px;
#editor {
position: absolute;
height: 100px;
width: 100px;
overflow: hidden;
}
#solIcon img {
top: -20px;
right: -10px;
position: absolute;
height: 100px;
}
#optimizeBox {
position: absolute;
top: 30px;
left: 720px;
font-size: 14px;
}
#input {
position: absolute;
top: 120px;
top: 0;
left: 0px;
width: 700px;
width: auto;
bottom: 0px;
right: 37em;
}
#input {
font-size: 15px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
min-width: 20vw;
}
#output {
#righthand-panel {
position: absolute;
top: 120px;
left: 720px;
right: 10px;
top: 0;
width: 37em;
max-width: 80vw;
right: 0;
bottom: 0px;
font-size: 14px;
overflow: auto;
border-left: 1px dotted black;
box-sizing: border-box;
}
#output {
border-top: 1px dotted black;
display: block;
}
#header {
margin-bottom: 4px;
font-size: 14px;
padding: 1em;
font-size: 12px;
}
#header h1 {
margin-top: 0;
}
#header .info { clear: left; }
#header #solIcon {
float: left;
height: 5em;
}
.col1 {
width: 18ex;
display: inline-block;
width: 30%;
float: left;
}
.col2 {
width: 60ex;
display: inline-block;
width: 70%;
float: left;
}
.row {
overflow: auto;
}
.gethDeployText {
border-color: #bebebe;
height: 2.5ex;
height: 2.5em;
width: 100%;
display: block;
}
.contractInstance {
background-color: #ccc;
margin-bottom: 1em;
padding: 0.6em;
}
.runButton {
width: 30ex;
.contractInstance.hide > *:not(.title) {
display: none;
}
.contractInstance .contractProperty input,
.contractInstance .contractProperty button {
text-align: left;
overflow: hidden;
padding: 0.3em;
width: 50%;
margin: 0;
}
.contractInstance {
margin-left: 2ex;
margin-bottom: 20px;
.contractOutput .contractInstance .contractProperty {
margin-bottom: 0;
}
.contractOutput .contractInstance .contractProperty .output {
padding: 0.4em;
background-color: #333;
color: white;
margin-bottom: 1em;
display: block;
}
.contractInstance .contractProperty .output:empty { display: none; }
.contractOutput {
border-bottom: 1px dotted black;
padding: 0.6em;
box-sizing: border-box;
}
.contractOutput .contractProperty {
margin-bottom: 0.6em;
}
.contractOutput .contractProperty .output {
display: inline;
}
.contractOutput .body {
margin-top: 10px;
}
.contractOutput.hide {
background-color: #4C4C67;
color: white;
}
.contractOutput.hide > *:not(.title) {
display: none;
}
.title {
margin: 0;
cursor: pointer;
font-family: monospace;
font-weight: bold;
}
.title:before {
content: "\25BC";
opacity: 0.5;
margin-right: 0.4em;
font-size: 10px;
}
.hide > .title:before {
content: "\25B6";
}
.contractOutput > .title {
border-bottom: #4C4C67;
}
.title .size {
font-weight: normal;
float: right;
}
.solError {
position: absolute;
background-color: rgba(255, 0, 0, 0.2);
z-index:40;
}
.error {
background-color: rgba(255, 0, 0, 0.5);
border-radius: 0;
word-wrap: break-word;
border: 1px solid #D00909;
}
#ghostbar {
width: 1px;
background-color: red;
opacity: 0.5;
position: absolute;
cursor: col-resize;
z-index: 9999;
top: 0;
bottom: 0;
}
#dragbar{
background-color: transparent;
position: absolute;
width: 5px;
left: 0;
top: 0;
bottom: 0;
cursor: col-resize;
z-index: 999;
}
input[readonly] {
padding: .4em;
border: 1px solid #ccc;
box-sizing: border-box;
display: block;
width: 100%;
}
</style>
<script src="libs/jquery-2.1.3.min.js"></script>
<script src="libs/ace.js"></script>
......@@ -80,369 +219,432 @@ body {
<script src="soljson.js"></script>
<script src="ethereumjs-vm.js"></script>
<script src="web3.min.js"></script>
<script src="ballot.sol.js"></script>
</head>
<body>
<div id="solIcon"><img src="solidity.svg"></div>
<h1 id="header">Solidity realtime compiler and runtime</h1>
Version: <span id="version">(loading)</span><br/>
Execution environment does not connect to any node, everyhing is in-memory only.<br/>
<b>Note:</b> If Chrome/Chromium reports &quot;Uncaught JavaScript Exception&quot;,
enable the debug console (Ctrl+Shift+i) and reload.
<div id="optimizeBox">
<input id="optimize" type="checkbox"><label for="optimize">optimize</label>
</div>
<div id="input">contract Ballot {
struct Voter {
uint weight;
bool voted;
uint8 vote;
address delegate;
}
struct Proposal {
uint voteCount;
}
address chairperson;
mapping(address => Voter) voters;
Proposal[] proposals;
// Create a new ballot with $(_numProposals) different proposals.
function Ballot(uint8 _numProposals) {
chairperson = msg.sender;
voters[chairperson].weight = 1;
proposals.length = _numProposals;
}
// Give $(voter) the right to vote on this ballot.
// May only be called by $(chairperson).
function giveRightToVote(address voter) {
if (msg.sender != chairperson || voters[voter].voted) return;
voters[voter].weight = 1;
}
// Delegate your vote to the voter $(to).
function delegate(address to) {
Voter sender = voters[msg.sender]; // assigns reference
if (sender.voted) return;
while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender)
to = voters[to].delegate;
if (to == msg.sender) return;
sender.voted = true;
sender.delegate = to;
Voter delegate = voters[to];
if (delegate.voted)
proposals[delegate.vote].voteCount += sender.weight;
else
delegate.weight += sender.weight;
}
// Give a single vote to proposal $(proposal).
function vote(uint8 proposal) {
Voter sender = voters[msg.sender];
if (sender.voted || proposal >= proposals.length) return;
sender.voted = true;
sender.vote = proposal;
proposals[proposal].voteCount += sender.weight;
}
function winningProposal() constant returns (uint8 winningProposal) {
uint256 winningVoteCount = 0;
for (uint8 proposal = 0; proposal < proposals.length; proposal++) {
if (proposals[proposal].voteCount > winningVoteCount) {
winningVoteCount = proposals[proposal].voteCount;
winningProposal = proposal;
}
++proposal;
}
}
}
</div>
<div id="output"></div>
<div style="height: 100px;"></div>
<p><small>Theme by <a href="https://github.com/orderedlist">orderedlist</a></small></p>
<script>
// ----------------- editor ----------------------
var editor = ace.edit("input");
editor.getSession().setMode("ace/mode/javascript");
editor.getSession().setTabSize(4);
editor.getSession().setUseSoftTabs(true);
// ----------------- compiler ----------------------
var compileJSON = Module.cwrap("compileJSON", "string", ["string", "number"]);
$('#version').text(Module.cwrap("version", "string", [])());
var previousInput = '';
var compile = function() {
var input = editor.getValue();
var optimize = document.querySelector('#optimize').checked;
try {
var data = $.parseJSON(compileJSON(input, optimize ? 1 : 0));
} catch (exception) {
renderError("Uncaught JavaScript Exception:\n" + exception);
return;
}
if (data['error'] !== undefined)
renderError(data['error']);
else
renderContracts(data, input);
}
var compileTimeout = null;
var onChange = function() {
var input = editor.getValue();
if (input == previousInput)
return;
previousInput = input;
if (compileTimeout) window.clearTimeout(compileTimeout);
compileTimeout = window.setTimeout(compile, 300);
};
onChange();
editor.getSession().on('change', onChange);
document.querySelector('#optimize').addEventListener('change', compile);
// ----------------- compiler output renderer ----------------------
var detailsOpen = {};
var renderError = function(message) {
$('#output').empty().append($('<pre></pre>').text(message));
};
var gethDeploy = function(contractName, interface, bytecode){
var code = "";
var funABI = getConstructorInterface($.parseJSON(interface));
$.each(funABI.inputs, function(i, inp) {
code += "var "+inp.name+" = /* var of type " + inp.type + " here */ ;\n";
});
code += "\nvar "+contractName+"Contract = web3.eth.contract("+interface.replace("\n","")+");"
+"\nvar "+contractName+" = "+contractName+"Contract.new(";
$.each(funABI.inputs, function(i, inp) {
code += "\n "+inp.name+",";
});
code += "\n {"+
"\n from: web3.eth.accounts[0], "+
"\n data: '"+bytecode+"', "+
"\n gas: 1000000"+
"\n }, function(e, contract){"+
"\n if(!e) {"+
"\n if(!contract.address) {"+
"\n console.log('Contract transaction sent! TransactionHash: ' + contract.transactionHash + ' waiting to be mined...');"+
"\n } else {"+
"\n console.log('Contract mined! Address: ' + contract.address);"+
"\n console.log(contract);"+
"\n }"+
"\n }})";
return code;
};
var renderContracts = function(data, source) {
$('#output').empty();
for (var contractName in data.contracts) {
var contract = data.contracts[contractName];
var contractOutput = $('<div class="contractOutput"/>')
.append($('<h3/>').text(contractName));
if (contract.bytecode.length > 0)
contractOutput
.append($('<div/>').text((contract.bytecode.length / 2) + ' bytes'))
.append(getExecuteInterface(contract, contractName))
.append(tableRow('Bytecode', contract.bytecode));
contractOutput
.append(tableRow('Interface', contract['interface']))
.append(textRow('Console deploy', gethDeploy(contractName.toLowerCase(),contract['interface'],contract.bytecode)))
.append(getDetails(contract, source, contractName));
$('#output').append(contractOutput);
}
$('.col2 input,textarea').click(function() { this.select(); } );
};
var tableRowItems = function(first, second) {
return $('<div/>')
.append($('<div class="col1">').append(first))
.append($('<div class="col2">').append(second));
};
var tableRow = function(description, data) {
return tableRowItems(
$('<span/>').text(description),
$('<input readonly="readonly"/>').val(data));
};
var textRow = function(description, data) {
return tableRowItems(
$('<strong/>').text(description),
$('<textarea readonly="readonly" class="gethDeployText"/>').val(data));
};
var getDetails = function(contract, source, contractName) {
var button = $('<button>Details</button>');
var details = $('<div style="display: none;"/>')
.append(tableRow('Solidity Interface', contract.solidity_interface))
.append(tableRow('Opcodes', contract.opcodes));
var funHashes = '';
for (var fun in contract.functionHashes)
funHashes += contract.functionHashes[fun] + ' ' + fun + '\n';
details.append($('<span class="col1">Functions</span>'));
details.append($('<pre/>').text(funHashes));
details.append($('<span class="col1">Gas Estimates</span>'));
details.append($('<pre/>').text(formatGasEstimates(contract.gasEstimates)));
if (contract.assembly !== null)
{
details.append($('<span class="col1">Assembly</span>'));
var assembly = $('<pre/>').text(formatAssemblyText(contract.assembly, '', source));
details.append(assembly);
}
button.click(function() { detailsOpen[contractName] = !detailsOpen[contractName]; details.toggle(); });
if (detailsOpen[contractName])
details.show();
return $('<div/>').append(button).append(details);
};
var formatGasEstimates = function(data) {
var gasToText = function(g) { return g === null ? 'unknown' : g; }
var text = '';
if ('creation' in data)
text += 'Creation: ' + gasToText(data.creation[0]) + ' + ' + gasToText(data.creation[1]) + '\n';
text += 'External:\n';
for (var fun in data.external)
text += ' ' + fun + ': ' + gasToText(data.external[fun]) + '\n';
text += 'Internal:\n';
for (var fun in data.internal)
text += ' ' + fun + ': ' + gasToText(data.internal[fun]) + '\n';
return text;
};
var formatAssemblyText = function(asm, prefix, source) {
if (typeof(asm) == typeof('') || asm === null || asm === undefined)
return prefix + asm + '\n';
var text = prefix + '.code\n';
$.each(asm['.code'], function(i, item) {
var v = item.value === undefined ? '' : item.value;
var src = '';
if (item.begin !== undefined && item.end != undefined)
src = source.slice(item.begin, item.end).replace('\n', '\\n', 'g');
if (src.length > 30)
src = src.slice(0, 30) + '...';
if (item.name != 'tag')
text += ' ';
text += prefix + item.name + ' ' + v + '\t\t\t' + src + '\n';
});
text += prefix + '.data\n';
if (asm['.data'])
$.each(asm['.data'], function(i, item) {
text += ' ' + prefix + '' + i + ':\n';
text += formatAssemblyText(item, prefix + ' ', source);
});
return text;
};
$('.asmOutput button').click(function() {$(this).parent().find('pre').toggle(); } )
// ----------------- VM ----------------------
var stateTrie = new EthVm.Trie();
var vm = new EthVm.VM(stateTrie);
//@todo this does not calculate the gas costs correctly but gets the job done.
var identityCode = 'return { gasUsed: 1, return: opts.data, exception: 1 };';
var identityAddr = ethUtil.pad(new Buffer('04', 'hex'), 20)
vm.loadPrecompiled(identityAddr, identityCode);
var secretKey = '3cd7232cd6f3fc66a57a6bedc1a8ed6c228fff0a327e169c2bcc5e869ed49511'
var publicKey = '0406cc661590d48ee972944b35ad13ff03c7876eae3fd191e8a2f77311b0a3c6613407b5005e63d7d8d76b89d5f900cde691497688bb281e07a5052ff61edebdc0'
var address = ethUtil.pubToAddress(new Buffer(publicKey, 'hex'));
var account = new EthVm.Account();
account.balance = 'f00000000000000001';
var nonce = 0;
stateTrie.put(address, account.serialize());
var runTx = function(data, to, cb) {
var tx = new EthVm.Transaction({
nonce: new Buffer([nonce++]), //@todo count beyond 255
gasPrice: '01',
gasLimit: '3000000',
to: to,
data: data
});
tx.sign(new Buffer(secretKey, 'hex'));
vm.runTx({tx: tx}, cb);
};
var getConstructorInterface = function(abi) {
var funABI = {'name':'','inputs':[],'type':'constructor','outputs':[]};
for (var i = 0; i < abi.length; i++)
if (abi[i].type == 'constructor') {
funABI.inputs = abi[i].inputs || [];
break;
}
return funABI;
};
var getCallButton = function(args) {
// args.abi, args.bytecode [constr only], args.address [fun only]
// args.appendFunctions [constr only]
var isConstructor = args.bytecode !== undefined;
var fun = new web3.eth.function(args.abi);
var inputs = '';
$.each(args.abi.inputs, function(i, inp) {
if (inputs != '') inputs += ', ';
inputs += inp.type + ' ' + inp.name;
});
var inputField = $('<input/>').attr('placeholder', inputs);
var outputSpan = $('<div/>');
var button = $('<button/>')
.text(args.bytecode ? 'Create' : fun.displayName())
.click(function() {
var funArgs = $.parseJSON('[' + inputField.val() + ']');
var data = fun.toPayload(funArgs).data;
if (data.slice(0, 2) == '0x') data = data.slice(2);
if (isConstructor)
data = args.bytecode + data.slice(8);
outputSpan.text(' ...');
runTx(data, args.address, function(err, result) {
if (err)
outputSpan.text(err);
else if (isConstructor) {
outputSpan.text(' Creation used ' + result.vm.gasUsed.toString(10) + ' gas.');
args.appendFunctions(result.createdAddress);
} else {
var outputObj = fun.unpackOutput('0x' + result.vm.return.toString('hex'));
outputSpan.text(' Returned: ' + JSON.stringify(outputObj));
<div id="editor">
<div id="input"></div>
</div>
<div id="righthand-panel">
<div id="dragbar"></div>
<div id="header">
<img id="solIcon" src="solidity.svg">
<h1>Solidity realtime<br/>compiler and runtime</h1>
<div class="info">
<p>Version: <span id="version">(loading)</span><br/>
Execution environment does not connect to any node, everyhing is in-memory only.<br/>
<strong>Note:</strong> If Chrome/Chromium reports &quot;Uncaught JavaScript Exception&quot;,
enable the debug console (Ctrl+Shift+i) and reload.</p>
</div>
<div id="optimizeBox">
<input id="editorWrap" type="checkbox"><label for="editorWrap">Text Wrap</label>
<input id="optimize" type="checkbox"><label for="optimize">Enable Optimization</label>
</div>
</div>
<div id="output"></div>
</div>
<script>
// ----------------- editor ----------------------
var SOL_CACHE_KEY = "sol-cache";
var editor = ace.edit("input");
var session = editor.getSession();
var Range = ace.require('ace/range').Range;
var errMarkerId = null;
var solCache = window.localStorage.getItem( SOL_CACHE_KEY );
editor.setValue( solCache || BALLOT_EXAMPLE, 1 );
session.setMode("ace/mode/javascript");
session.setTabSize(4);
session.setUseSoftTabs(true);
// ----------------- resizeable ui ---------------
var EDITOR_SIZE_CACHE_KEY = "editor-size-cache";
var dragging = false;
$('#dragbar').mousedown(function(e){
e.preventDefault();
dragging = true;
var main = $('#righthand-panel');
var ghostbar = $('<div id="ghostbar">', {
css: {
top: main.offset().top,
left: main.offset().left
}
}).prependTo('body');
$(document).mousemove(function(e){
ghostbar.css("left",e.pageX+2);
});
});
if (!isConstructor)
button.addClass('runButton');
var c = $('<div/>')
.append(button);
if (args.abi.inputs.length > 0)
c.append(inputField);
return c.append(outputSpan);
};
var getExecuteInterface = function(contract, name) {
var abi = $.parseJSON(contract.interface);
var execInter = $('<div/>');
var funABI = getConstructorInterface(abi);
var appendFunctions = function(address) {
var instance = $('<div class="contractInstance"/>');
instance.append($('<span/>').text('Contract at address ' + address.toString('hex')));
$.each(abi, function(i, funABI) {
if (funABI.type != 'function') return;
instance.append(getCallButton({
abi: funABI,
address: address
}));
var $body = $('body');
function setEditorSize (delta) {
$('#righthand-panel').css("width", delta);
$('#editor').css("right", delta);
onResize();
}
$(document).mouseup(function(e){
if (dragging) {
var delta = $body.width() - e.pageX+2;
$('#ghostbar').remove();
$(document).unbind('mousemove');
dragging = false;
setEditorSize( delta )
window.localStorage.setItem( EDITOR_SIZE_CACHE_KEY, delta );
}
});
execInter.append(instance);
};
execInter
.append(getCallButton({
abi: funABI,
bytecode: contract.bytecode,
appendFunctions: appendFunctions
}));
return execInter;
};
</script>
// set cached defaults
var cachedSize = window.localStorage.getItem( EDITOR_SIZE_CACHE_KEY );
if (cachedSize) setEditorSize( cachedSize );
// ----------------- editor resize ---------------
function onResize() {
editor.resize();
session.setUseWrapMode(document.querySelector('#editorWrap').checked);
if(session.getUseWrapMode()) {
var characterWidth = editor.renderer.characterWidth;
var contentWidth = editor.container.ownerDocument.getElementsByClassName("ace_scroller")[0].clientWidth;
if(contentWidth > 0) {
session.setWrapLimit(parseInt(contentWidth / characterWidth, 10));
}
}
}
window.onresize = onResize;
onResize();
document.querySelector('#editor').addEventListener('change', onResize );
// ----------------- compiler ----------------------
var compileJSON = Module.cwrap("compileJSON", "string", ["string", "number"]);
$('#version').text(Module.cwrap("version", "string", [])());
var previousInput = '';
var compile = function() {
editor.getSession().clearAnnotations();
editor.getSession().removeMarker(errMarkerId);
var input = editor.getValue();
var optimize = document.querySelector('#optimize').checked;
try {
var data = $.parseJSON(compileJSON(input, optimize ? 1 : 0));
} catch (exception) {
renderError("Uncaught JavaScript Exception:\n" + exception);
return;
}
if (data['error'] !== undefined)
renderError(data['error']);
else
renderContracts(data, input);
}
var compileTimeout = null;
var onChange = function() {
var input = editor.getValue();
if (input === "") {
window.localStorage.setItem( SOL_CACHE_KEY, '' )
return;
}
if (input === previousInput)
return;
previousInput = input;
if (compileTimeout) window.clearTimeout(compileTimeout);
compileTimeout = window.setTimeout(compile, 300);
};
onChange();
editor.getSession().on('change', onChange);
document.querySelector('#optimize').addEventListener('change', compile);
// ----------------- compiler output renderer ----------------------
var detailsOpen = {};
var renderError = function(message) {
var $output = $('#output').empty()
var err = message.match(/^:([0-9]*):([0-9]*)/)
if (err && err.length) {
var errLine = parseInt( err[1], 10 ) - 1;
var errCol = err[2] ? parseInt( err[2], 10 ) : 0;
$output.append($('<pre class="error"></pre>').text(message));
editor.getSession().setAnnotations([{
row: errLine,
column: errCol,
text: message,
type: "error"
}]);
}
};
var gethDeploy = function(contractName, interface, bytecode){
var code = "";
var funABI = getConstructorInterface($.parseJSON(interface));
$.each(funABI.inputs, function(i, inp) {
code += "var "+inp.name+" = /* var of type " + inp.type + " here */ ;\n";
});
code += "\nvar "+contractName+"Contract = web3.eth.contract("+interface.replace("\n","")+");"
+"\nvar "+contractName+" = "+contractName+"Contract.new(";
$.each(funABI.inputs, function(i, inp) {
code += "\n "+inp.name+",";
});
code += "\n {"+
"\n from: web3.eth.accounts[0], "+
"\n data: '"+bytecode+"', "+
"\n gas: 1000000"+
"\n }, function(e, contract){"+
"\n if (typeof contract.address != 'undefined') {"+
"\n console.log(e, contract);"+
"\n console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);" +
"\n }" +
"\n })";
return code;
};
var combined = function(contractName, interface, bytecode){
return JSON.stringify( [{name: contractName, interface: interface, bytecode: bytecode}]);
};
var renderContracts = function(data, source) {
window.localStorage.setItem( SOL_CACHE_KEY, source );
$('#output').empty();
for (var contractName in data.contracts) {
var contract = data.contracts[contractName];
var title = $('<h3 class="title"/>').text(contractName);
var contractOutput = $('<div class="contractOutput"/>')
.append(title);
var body = $('<div class="body" />')
contractOutput.append( body );
if (contract.bytecode.length > 0)
title.append($('<div class="size"/>').text((contract.bytecode.length / 2) + ' bytes'))
body.append(getExecuteInterface(contract, contractName))
.append(tableRow('Bytecode', contract.bytecode));
body.append(tableRow('Interface', contract['interface']))
.append(textRow('Web3 deploy', gethDeploy(contractName.toLowerCase(),contract['interface'],contract.bytecode), 'deploy'))
.append(textRow('uDApp', combined(contractName,contract['interface'],contract.bytecode), 'deploy'))
.append(getDetails(contract, source, contractName));
$('#output').append(contractOutput);
title.click(function(ev){ $(this).parent().toggleClass('hide') });
}
$('.col2 input,textarea').click(function() { this.select(); } );
};
var tableRowItems = function(first, second, cls) {
return $('<div class="row"/>')
.addClass(cls)
.append($('<div class="col1">').append(first))
.append($('<div class="col2">').append(second));
};
var tableRow = function(description, data) {
return tableRowItems(
$('<span/>').text(description),
$('<input readonly="readonly"/>').val(data));
};
var textRow = function(description, data, cls) {
return tableRowItems(
$('<strong/>').text(description),
$('<textarea readonly="readonly" class="gethDeployText"/>').val(data),
cls);
};
var getDetails = function(contract, source, contractName) {
var button = $('<button>Details</button>');
var details = $('<div style="display: none;"/>')
.append(tableRow('Solidity Interface', contract.solidity_interface))
.append(tableRow('Opcodes', contract.opcodes));
var funHashes = '';
for (var fun in contract.functionHashes)
funHashes += contract.functionHashes[fun] + ' ' + fun + '\n';
details.append($('<span class="col1">Functions</span>'));
details.append($('<pre/>').text(funHashes));
details.append($('<span class="col1">Gas Estimates</span>'));
details.append($('<pre/>').text(formatGasEstimates(contract.gasEstimates)));
if (contract.assembly !== null)
{
details.append($('<span class="col1">Assembly</span>'));
var assembly = $('<pre/>').text(formatAssemblyText(contract.assembly, '', source));
details.append(assembly);
}
button.click(function() { detailsOpen[contractName] = !detailsOpen[contractName]; details.toggle(); });
if (detailsOpen[contractName])
details.show();
return $('<div/>').append(button).append(details);
};
var formatGasEstimates = function(data) {
var gasToText = function(g) { return g === null ? 'unknown' : g; }
var text = '';
if ('creation' in data)
text += 'Creation: ' + gasToText(data.creation[0]) + ' + ' + gasToText(data.creation[1]) + '\n';
text += 'External:\n';
for (var fun in data.external)
text += ' ' + fun + ': ' + gasToText(data.external[fun]) + '\n';
text += 'Internal:\n';
for (var fun in data.internal)
text += ' ' + fun + ': ' + gasToText(data.internal[fun]) + '\n';
return text;
};
var formatAssemblyText = function(asm, prefix, source) {
if (typeof(asm) == typeof('') || asm === null || asm === undefined)
return prefix + asm + '\n';
var text = prefix + '.code\n';
$.each(asm['.code'], function(i, item) {
var v = item.value === undefined ? '' : item.value;
var src = '';
if (item.begin !== undefined && item.end != undefined)
src = source.slice(item.begin, item.end).replace('\n', '\\n', 'g');
if (src.length > 30)
src = src.slice(0, 30) + '...';
if (item.name != 'tag')
text += ' ';
text += prefix + item.name + ' ' + v + '\t\t\t' + src + '\n';
});
text += prefix + '.data\n';
if (asm['.data'])
$.each(asm['.data'], function(i, item) {
text += ' ' + prefix + '' + i + ':\n';
text += formatAssemblyText(item, prefix + ' ', source);
});
return text;
};
$('.asmOutput button').click(function() {$(this).parent().find('pre').toggle(); } )
// ----------------- VM ----------------------
var stateTrie = new EthVm.Trie();
var vm = new EthVm.VM(stateTrie);
//@todo this does not calculate the gas costs correctly but gets the job done.
var identityCode = 'return { gasUsed: 1, return: opts.data, exception: 1 };';
var identityAddr = ethUtil.pad(new Buffer('04', 'hex'), 20)
vm.loadPrecompiled(identityAddr, identityCode);
var secretKey = '3cd7232cd6f3fc66a57a6bedc1a8ed6c228fff0a327e169c2bcc5e869ed49511'
var publicKey = '0406cc661590d48ee972944b35ad13ff03c7876eae3fd191e8a2f77311b0a3c6613407b5005e63d7d8d76b89d5f900cde691497688bb281e07a5052ff61edebdc0'
var address = ethUtil.pubToAddress(new Buffer(publicKey, 'hex'));
var account = new EthVm.Account();
account.balance = 'f00000000000000001';
var nonce = 0;
stateTrie.put(address, account.serialize());
var runTx = function(data, to, cb) {
var tx = new EthVm.Transaction({
nonce: new Buffer([nonce++]), //@todo count beyond 255
gasPrice: '01',
gasLimit: '3000000',
to: to,
data: data
});
tx.sign(new Buffer(secretKey, 'hex'));
vm.runTx({tx: tx}, cb);
};
var getConstructorInterface = function(abi) {
var funABI = {'name':'','inputs':[],'type':'constructor','outputs':[]};
for (var i = 0; i < abi.length; i++)
if (abi[i].type == 'constructor') {
funABI.inputs = abi[i].inputs || [];
break;
}
return funABI;
};
var getCallButton = function(args) {
// args.abi, args.bytecode [constr only], args.address [fun only]
// args.appendFunctions [constr only]
var isConstructor = args.bytecode !== undefined;
var fun = new web3.eth.function(args.abi);
var inputs = '';
$.each(args.abi.inputs, function(i, inp) {
if (inputs != '') inputs += ', ';
inputs += inp.type + ' ' + inp.name;
});
var inputField = $('<input/>').attr('placeholder', inputs);
var outputSpan = $('<div class="output"/>');
var button = $('<button/>')
.text(args.bytecode ? 'Create' : fun.displayName())
.click(function() {
var funArgs = $.parseJSON('[' + inputField.val() + ']');
var data = fun.toPayload(funArgs).data;
if (data.slice(0, 2) == '0x') data = data.slice(2);
if (isConstructor)
data = args.bytecode + data.slice(8);
outputSpan.text('...');
runTx(data, args.address, function(err, result) {
if (err)
outputSpan.text(err);
else if (isConstructor) {
outputSpan.text(' Creation used ' + result.vm.gasUsed.toString(10) + ' gas.');
args.appendFunctions(result.createdAddress);
} else {
var outputObj = fun.unpackOutput('0x' + result.vm.return.toString('hex'));
outputSpan.text(' Returned: ' + JSON.stringify(outputObj));
}
});
});
if (!isConstructor)
button.addClass('runButton');
var c = $('<div class="contractProperty"/>')
.append(button);
if (args.abi.inputs.length > 0)
c.append(inputField);
return c.append(outputSpan);
};
var getExecuteInterface = function(contract, name) {
var abi = $.parseJSON(contract.interface);
var execInter = $('<div/>');
var funABI = getConstructorInterface(abi);
var appendFunctions = function(address) {
var instance = $('<div class="contractInstance"/>');
var title = $('<span class="title"/>').text('Contract at ' + address.toString('hex') );
instance.append(title);
$.each(abi, function(i, funABI) {
if (funABI.type != 'function') return;
instance.append(getCallButton({
abi: funABI,
address: address
}));
});
execInter.append(instance);
title.click(function(ev){ $(this).parent().toggleClass('hide') });
};
execInter
.append(getCallButton({
abi: funABI,
bytecode: contract.bytecode,
appendFunctions: appendFunctions
}));
return execInter;
};
</script>
</body>
</html>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 3840 2160" enable-background="new 0 0 3840 2160" xml:space="preserve">
<g>
<polyline opacity="0.45" points="2063.6,490.6 1919,747.6 1630,747.6 1774.5,490.6 2063.6,490.6 "/>
<polygon opacity="0.6" points="1919,747.6 2208.1,747.6 2063.6,490.6 1774.5,490.6 "/>
<polygon opacity="0.8" points="1774.5,1004.5 1919,747.6 1774.5,490.6 1630,747.6 "/>
<polyline opacity="0.45" points="1775.9,1390 1920.5,1133 2209.6,1133 2065,1390 1775.9,1390 "/>
<polygon opacity="0.6" points="1920.5,1133 1631.4,1133 1775.9,1390 2065,1390 "/>
<polygon opacity="0.8" points="2065,876.1 1920.5,1133 2065,1390 2209.6,1133 "/>
<path fill="#010101" d="M1602.3,1636c0,4.1,1.7,7.1,5,9.1c3.3,2,7.4,3.7,12.3,5c4.9,1.3,10.3,2.5,16.1,3.5c5.8,1,11.2,2.5,16.1,4.4
c4.9,1.9,9,4.6,12.3,8c3.3,3.4,5,8.1,5,14c0,5-1.2,9.3-3.5,12.9c-2.3,3.6-5.3,6.6-8.9,8.9c-3.6,2.3-7.6,4.1-12.1,5.3
c-4.4,1.2-8.8,1.8-13,1.8c-4.6,0-9.2-0.5-13.7-1.5c-4.5-1-8.6-2.6-12.2-4.8c-3.6-2.2-6.6-5.1-8.9-8.7c-2.3-3.6-3.5-8.1-3.5-13.4
c0-1.8,0.2-3.4,0.7-4.6c0.5-1.2,1.8-1.8,4-1.8c1.1,0,1.9,0.5,2.4,1.5c0.5,1,0.7,2,0.7,2.9c0,4.6,0.8,8.4,2.5,11.4
c1.7,3,3.9,5.3,6.8,6.9c2.9,1.7,6.1,2.8,9.8,3.5c3.7,0.6,7.5,1,11.4,1c3.1,0,6.5-0.4,10-1.2c3.5-0.8,6.7-2.1,9.6-3.7
c2.9-1.7,5.3-3.8,7.2-6.5c1.9-2.7,2.9-5.9,2.9-9.6c0-4.6-1.7-8.2-5-10.7c-3.3-2.5-7.4-4.5-12.3-6c-4.9-1.5-10.3-2.7-16.1-3.6
c-5.8-0.9-11.2-2.3-16.1-4c-4.9-1.8-9-4.1-12.3-7.1c-3.3-3-5-7.1-5-12.5c0-4.6,1.2-8.5,3.5-11.5c2.3-3,5.2-5.4,8.7-7.2
c3.5-1.8,7.3-3,11.5-3.6c4.2-0.6,8.1-1,11.8-1c4.4,0,8.8,0.5,13.2,1.4c4.3,0.9,8.3,2.4,11.8,4.4c3.5,2,6.4,4.8,8.6,8.3
c2.2,3.5,3.3,7.9,3.3,13c0,1.1-0.5,2-1.4,2.6c-0.9,0.7-1.8,1-2.8,1c-1.3,0-2.2-0.5-2.8-1.4c-0.6-0.9-0.8-1.8-0.8-2.8
c-0.7-4.1-2.1-7.3-4-9.8c-1.9-2.5-4.3-4.4-6.9-5.7c-2.7-1.3-5.6-2.2-8.7-2.6c-3.1-0.5-6.3-0.7-9.4-0.7c-2.6,0-5.5,0.2-8.6,0.6
c-3.1,0.4-6.1,1.1-9,2.2c-2.9,1.1-5.3,2.6-7.2,4.6C1603.3,1630,1602.3,1632.7,1602.3,1636z"/>
<path fill="#010101" d="M1748.3,1611.9c6.5,0,12.5,1.3,18,4c5.5,2.7,10.3,6.2,14.3,10.7c4,4.4,7.1,9.6,9.3,15.4
c2.2,5.8,3.3,11.9,3.3,18.2c0,6.3-1.1,12.3-3.3,18.2c-2.2,5.8-5.3,10.9-9.3,15.4c-4,4.4-8.7,8-14.3,10.7c-5.5,2.7-11.5,4-18,4
c-6.5,0-12.4-1.3-17.9-4c-5.5-2.7-10.2-6.2-14.1-10.7c-4-4.4-7.1-9.6-9.3-15.4c-2.2-5.8-3.3-11.9-3.3-18.2c0-6.3,1.1-12.3,3.3-18.2
c2.2-5.8,5.3-10.9,9.3-15.4c4-4.4,8.7-8,14.1-10.7C1735.9,1613.2,1741.8,1611.9,1748.3,1611.9z M1748.3,1700.5
c5.5,0,10.6-1.2,15.1-3.5c4.5-2.3,8.4-5.3,11.6-9c3.2-3.7,5.7-8,7.5-12.9c1.8-4.9,2.6-9.9,2.6-15.1c0-5.2-0.9-10.2-2.6-15
c-1.8-4.8-4.3-9-7.5-12.7c-3.2-3.7-7.1-6.7-11.6-9c-4.5-2.3-9.6-3.5-15.1-3.5c-5.4,0-10.3,1.2-14.8,3.5c-4.5,2.3-8.4,5.3-11.6,9
c-3.2,3.7-5.8,7.9-7.6,12.7c-1.8,4.8-2.8,9.8-2.8,15c0,5.2,0.9,10.2,2.8,15.1c1.8,4.9,4.4,9.2,7.6,12.9c3.2,3.7,7.1,6.7,11.6,9
C1738,1699.4,1742.9,1700.5,1748.3,1700.5z"/>
<path fill="#010101" d="M1833.8,1536.8c1.1,0,2,0.4,2.8,1.2c0.7,0.8,1.1,1.7,1.1,2.6V1703c0,0.9-0.4,1.8-1.1,2.6
c-0.7,0.8-1.7,1.2-2.8,1.2c-1.1,0-2-0.4-2.8-1.2c-0.7-0.8-1.1-1.7-1.1-2.6v-162.4c0-0.9,0.4-1.8,1.1-2.6
C1831.7,1537.2,1832.7,1536.8,1833.8,1536.8z"/>
<path fill="#010101" d="M1883.2,1587.5c0,1.7-0.6,3.1-1.9,4.3c-1.3,1.2-2.8,1.8-4.4,1.8c-1.8,0-3.4-0.6-4.6-1.8
c-1.2-1.2-1.8-2.6-1.8-4.3c0-1.8,0.6-3.4,1.8-4.6c1.2-1.2,2.7-1.8,4.6-1.8c1.7,0,3.1,0.6,4.4,1.8
C1882.6,1584.1,1883.2,1585.6,1883.2,1587.5z M1876.9,1614.6c0.9,0,1.8,0.4,2.6,1.2c0.8,0.8,1.2,1.7,1.2,2.6v84.2
c0,0.9-0.4,1.8-1.2,2.6c-0.8,0.8-1.7,1.2-2.6,1.2c-1.1,0-2-0.4-2.8-1.2c-0.7-0.8-1.1-1.7-1.1-2.6v-84.2c0-0.9,0.4-1.8,1.1-2.6
C1874.8,1615.1,1875.8,1614.6,1876.9,1614.6z"/>
<path fill="#010101" d="M2003.2,1536.5c1.1,0,2,0.4,2.8,1.2c0.7,0.8,1.1,1.7,1.1,2.6v162.1c0,2.6-1.3,3.9-3.9,3.9
c-2.6,0-3.9-1.3-3.9-3.9v-17.7c-3.9,7.2-9.2,13-16.1,17.5c-6.8,4.4-14.4,6.7-22.7,6.7c-6.5,0-12.4-1.3-17.9-4
c-5.5-2.7-10.2-6.2-14.1-10.7c-4-4.4-7.1-9.6-9.3-15.4c-2.2-5.8-3.3-11.9-3.3-18.2c0-6.3,1.1-12.3,3.3-18.2
c2.2-5.8,5.3-10.9,9.3-15.4c4-4.4,8.7-8,14.1-10.7c5.4-2.7,11.4-4,17.9-4c8.3,0,15.9,2.3,22.7,6.8c6.8,4.5,12.2,10.4,16.1,17.6
v-96.4c0-0.9,0.4-1.8,1.1-2.6C2001.2,1536.9,2002.1,1536.5,2003.2,1536.5z M1960.5,1701.1c5.5,0,10.6-1.2,15.1-3.5
c4.5-2.3,8.4-5.3,11.6-9c3.2-3.7,5.7-8,7.5-12.9c1.8-4.9,2.6-9.9,2.6-15.1c0-5.2-0.9-10.2-2.6-15.1c-1.8-4.9-4.3-9.2-7.5-12.9
c-3.2-3.7-7.1-6.7-11.6-9c-4.5-2.3-9.6-3.5-15.1-3.5c-5.4,0-10.3,1.2-14.8,3.5c-4.5,2.3-8.4,5.3-11.6,9c-3.2,3.7-5.8,8-7.6,12.9
c-1.8,4.9-2.8,9.9-2.8,15.1c0,5.2,0.9,10.2,2.8,15.1c1.8,4.9,4.4,9.2,7.6,12.9c3.2,3.7,7.1,6.7,11.6,9
C1950.2,1699.9,1955.2,1701.1,1960.5,1701.1z"/>
<path fill="#010101" d="M2054.1,1587.5c0,1.7-0.6,3.1-1.9,4.3c-1.3,1.2-2.8,1.8-4.4,1.8c-1.8,0-3.4-0.6-4.6-1.8
c-1.2-1.2-1.8-2.6-1.8-4.3c0-1.8,0.6-3.4,1.8-4.6c1.2-1.2,2.7-1.8,4.6-1.8c1.7,0,3.1,0.6,4.4,1.8
C2053.4,1584.1,2054.1,1585.6,2054.1,1587.5z M2047.7,1614.6c0.9,0,1.8,0.4,2.6,1.2c0.8,0.8,1.2,1.7,1.2,2.6v84.2
c0,0.9-0.4,1.8-1.2,2.6c-0.8,0.8-1.7,1.2-2.6,1.2c-1.1,0-2-0.4-2.8-1.2c-0.7-0.8-1.1-1.7-1.1-2.6v-84.2c0-0.9,0.4-1.8,1.1-2.6
C2045.7,1615.1,2046.6,1614.6,2047.7,1614.6z"/>
<path fill="#010101" d="M2135.2,1614.1c1.1,0,2,0.4,2.8,1.2c0.7,0.8,1.1,1.7,1.1,2.6c0,2.6-1.3,3.9-3.9,3.9h-20.8v81.5
c0,0.9-0.4,1.8-1.1,2.6c-0.7,0.8-1.7,1.2-2.8,1.2c-1.1,0-2-0.4-2.8-1.2c-0.7-0.8-1.1-1.7-1.1-2.6v-81.5h-20c-2.6,0-3.9-1.3-3.9-3.9
c0-0.9,0.4-1.8,1.1-2.6c0.7-0.8,1.7-1.2,2.8-1.2h20v-29.9c0-2.6,1.3-3.9,3.9-3.9c2.6,0,3.9,1.3,3.9,3.9v29.9H2135.2z"/>
<path fill="#010101" d="M2242.7,1613.8c2.6,0,3.9,1.3,3.9,3.9c0,0.2-0.7,2.2-2.2,6.1c-1.5,3.9-3.4,8.9-5.7,15.1
c-2.3,6.2-5,13.3-8,21.2c-3,7.9-6.2,16.1-9.6,24.5c-3.3,8.4-6.6,16.7-9.7,24.8c-3.1,8.1-6.1,15.6-8.7,22.3
c-2.7,6.7-4.9,12.5-6.8,17.2c-1.8,4.7-3,7.7-3.6,9c-0.9,1.7-2.1,2.5-3.6,2.5c-0.9,0-1.8-0.4-2.6-1.2c-0.8-0.8-1.2-1.7-1.2-2.6
c0-0.4,0.5-1.8,1.4-4.3c0.9-2.5,2-5.5,3.3-9c1.3-3.5,2.8-7.3,4.4-11.5c1.7-4.2,3.2-8.1,4.7-11.9c1.5-3.8,2.8-7.1,3.9-9.8
c1.1-2.8,1.8-4.6,2.2-5.5c-0.2-0.2-1.2-2.4-3-6.6c-1.8-4.2-4.1-9.6-6.8-15.9c-2.7-6.4-5.5-13.3-8.5-20.6c-3-7.4-5.7-14.3-8.3-20.6
c-2.6-6.4-4.8-11.7-6.5-16.1c-1.8-4.3-2.6-6.6-2.6-6.8c0-2.6,1.3-3.9,3.9-3.9c1.8,0,3,0.7,3.6,2.2l32.1,78.4l30.5-78.1
C2239.6,1614.6,2240.8,1613.8,2242.7,1613.8z"/>
</g>
</svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="1472px" height="1472px" viewBox="0 0 1472 1472" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.1.1 (8761) - http://www.bohemiancoding.com/sketch -->
<title>Vector 1</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="solidity" sketch:type="MSLayerGroup" transform="translate(402.000000, 118.000000)">
<g id="Group" sketch:type="MSShapeGroup">
<path d="M470.6,-0.4 L326,256.6 L37,256.6 L181.5,-0.4 L470.6,-0.4" id="Shape" opacity="0.45" fill="#000000"></path>
<path d="M326,256.6 L615.1,256.6 L470.6,-0.4 L181.5,-0.4 L326,256.6 Z" id="Shape" opacity="0.6" fill="#000000"></path>
<path d="M181.5,513.5 L326,256.6 L181.5,-0.4 L37,256.6 L181.5,513.5 Z" id="Shape" opacity="0.8" fill="#000000"></path>
<path d="M182.9,899 L327.5,642 L616.6,642 L472,899 L182.9,899" id="Shape" opacity="0.45" fill="#000000"></path>
<path d="M327.5,642 L38.4,642 L182.9,899 L472,899 L327.5,642 Z" id="Shape" opacity="0.6" fill="#000000"></path>
<path d="M472,385.1 L327.5,642 L472,899 L616.6,642 L472,385.1 Z" id="Shape" opacity="0.8" fill="#000000"></path>
<path d="M9.3,1145 C9.3,1149.1 11,1152.1 14.3,1154.1 C17.6,1156.1 21.7,1157.8 26.6,1159.1 C31.5,1160.4 36.9,1161.6 42.7,1162.6 C48.5,1163.6 53.9,1165.1 58.8,1167 C63.7,1168.9 67.8,1171.6 71.1,1175 C74.4,1178.4 76.1,1183.1 76.1,1189 C76.1,1194 74.9,1198.3 72.6,1201.9 C70.3,1205.5 67.3,1208.5 63.7,1210.8 C60.1,1213.1 56.1,1214.9 51.6,1216.1 C47.2,1217.3 42.8,1217.9 38.6,1217.9 C34,1217.9 29.4,1217.4 24.9,1216.4 C20.4,1215.4 16.3,1213.8 12.7,1211.6 C9.1,1209.4 6.1,1206.5 3.8,1202.9 C1.5,1199.3 0.3,1194.8 0.3,1189.5 C0.3,1187.7 0.5,1186.1 1,1184.9 C1.5,1183.7 2.8,1183.1 5,1183.1 C6.1,1183.1 6.9,1183.6 7.4,1184.6 C7.9,1185.6 8.1,1186.6 8.1,1187.5 C8.1,1192.1 8.9,1195.9 10.6,1198.9 C12.3,1201.9 14.5,1204.2 17.4,1205.8 C20.3,1207.5 23.5,1208.6 27.2,1209.3 C30.9,1209.9 34.7,1210.3 38.6,1210.3 C41.7,1210.3 45.1,1209.9 48.6,1209.1 C52.1,1208.3 55.3,1207 58.2,1205.4 C61.1,1203.7 63.5,1201.6 65.4,1198.9 C67.3,1196.2 68.3,1193 68.3,1189.3 C68.3,1184.7 66.6,1181.1 63.3,1178.6 C60,1176.1 55.9,1174.1 51,1172.6 C46.1,1171.1 40.7,1169.9 34.9,1169 C29.1,1168.1 23.7,1166.7 18.8,1165 C13.9,1163.2 9.8,1160.9 6.5,1157.9 C3.2,1154.9 1.5,1150.8 1.5,1145.4 C1.5,1140.8 2.7,1136.9 5,1133.9 C7.3,1130.9 10.2,1128.5 13.7,1126.7 C17.2,1124.9 21,1123.7 25.2,1123.1 C29.4,1122.5 33.3,1122.1 37,1122.1 C41.4,1122.1 45.8,1122.6 50.2,1123.5 C54.5,1124.4 58.5,1125.9 62,1127.9 C65.5,1129.9 68.4,1132.7 70.6,1136.2 C72.8,1139.7 73.9,1144.1 73.9,1149.2 C73.9,1150.3 73.4,1151.2 72.5,1151.8 C71.6,1152.5 70.7,1152.8 69.7,1152.8 C68.4,1152.8 67.5,1152.3 66.9,1151.4 C66.3,1150.5 66.1,1149.6 66.1,1148.6 C65.4,1144.5 64,1141.3 62.1,1138.8 C60.2,1136.3 57.8,1134.4 55.2,1133.1 C52.5,1131.8 49.6,1130.9 46.5,1130.5 C43.4,1130 40.2,1129.8 37.1,1129.8 C34.5,1129.8 31.6,1130 28.5,1130.4 C25.4,1130.8 22.4,1131.5 19.5,1132.6 C16.6,1133.7 14.2,1135.2 12.3,1137.2 C10.3,1139 9.3,1141.7 9.3,1145 L9.3,1145 Z" id="Shape" fill="#010101"></path>
<path d="M155.3,1120.9 C161.8,1120.9 167.8,1122.2 173.3,1124.9 C178.8,1127.6 183.6,1131.1 187.6,1135.6 C191.6,1140 194.7,1145.2 196.9,1151 C199.1,1156.8 200.2,1162.9 200.2,1169.2 C200.2,1175.5 199.1,1181.5 196.9,1187.4 C194.7,1193.2 191.6,1198.3 187.6,1202.8 C183.6,1207.2 178.9,1210.8 173.3,1213.5 C167.8,1216.2 161.8,1217.5 155.3,1217.5 C148.8,1217.5 142.9,1216.2 137.4,1213.5 C131.9,1210.8 127.2,1207.3 123.3,1202.8 C119.3,1198.4 116.2,1193.2 114,1187.4 C111.8,1181.6 110.7,1175.5 110.7,1169.2 C110.7,1162.9 111.8,1156.9 114,1151 C116.2,1145.2 119.3,1140.1 123.3,1135.6 C127.3,1131.2 132,1127.6 137.4,1124.9 C142.9,1122.2 148.8,1120.9 155.3,1120.9 L155.3,1120.9 Z M155.3,1209.5 C160.8,1209.5 165.9,1208.3 170.4,1206 C174.9,1203.7 178.8,1200.7 182,1197 C185.2,1193.3 187.7,1189 189.5,1184.1 C191.3,1179.2 192.1,1174.2 192.1,1169 C192.1,1163.8 191.2,1158.8 189.5,1154 C187.7,1149.2 185.2,1145 182,1141.3 C178.8,1137.6 174.9,1134.6 170.4,1132.3 C165.9,1130 160.8,1128.8 155.3,1128.8 C149.9,1128.8 145,1130 140.5,1132.3 C136,1134.6 132.1,1137.6 128.9,1141.3 C125.7,1145 123.1,1149.2 121.3,1154 C119.5,1158.8 118.5,1163.8 118.5,1169 C118.5,1174.2 119.4,1179.2 121.3,1184.1 C123.1,1189 125.7,1193.3 128.9,1197 C132.1,1200.7 136,1203.7 140.5,1206 C145,1208.4 149.9,1209.5 155.3,1209.5 L155.3,1209.5 Z" id="Shape" fill="#010101"></path>
<path d="M240.8,1045.8 C241.9,1045.8 242.8,1046.2 243.6,1047 C244.3,1047.8 244.7,1048.7 244.7,1049.6 L244.7,1212 C244.7,1212.9 244.3,1213.8 243.6,1214.6 C242.9,1215.4 241.9,1215.8 240.8,1215.8 C239.7,1215.8 238.8,1215.4 238,1214.6 C237.3,1213.8 236.9,1212.9 236.9,1212 L236.9,1049.6 C236.9,1048.7 237.3,1047.8 238,1047 C238.7,1046.2 239.7,1045.8 240.8,1045.8 L240.8,1045.8 Z" id="Shape" fill="#010101"></path>
<path d="M290.2,1096.5 C290.2,1098.2 289.6,1099.6 288.3,1100.8 C287,1102 285.5,1102.6 283.9,1102.6 C282.1,1102.6 280.5,1102 279.3,1100.8 C278.1,1099.6 277.5,1098.2 277.5,1096.5 C277.5,1094.7 278.1,1093.1 279.3,1091.9 C280.5,1090.7 282,1090.1 283.9,1090.1 C285.6,1090.1 287,1090.7 288.3,1091.9 C289.6,1093.1 290.2,1094.6 290.2,1096.5 L290.2,1096.5 Z M283.9,1123.6 C284.8,1123.6 285.7,1124 286.5,1124.8 C287.3,1125.6 287.7,1126.5 287.7,1127.4 L287.7,1211.6 C287.7,1212.5 287.3,1213.4 286.5,1214.2 C285.7,1215 284.8,1215.4 283.9,1215.4 C282.8,1215.4 281.9,1215 281.1,1214.2 C280.4,1213.4 280,1212.5 280,1211.6 L280,1127.4 C280,1126.5 280.4,1125.6 281.1,1124.8 C281.8,1124.1 282.8,1123.6 283.9,1123.6 L283.9,1123.6 Z" id="Shape" fill="#010101"></path>
<path d="M410.2,1045.5 C411.3,1045.5 412.2,1045.9 413,1046.7 C413.7,1047.5 414.1,1048.4 414.1,1049.3 L414.1,1211.4 C414.1,1214 412.8,1215.3 410.2,1215.3 C407.6,1215.3 406.3,1214 406.3,1211.4 L406.3,1193.7 C402.4,1200.9 397.1,1206.7 390.2,1211.2 C383.4,1215.6 375.8,1217.9 367.5,1217.9 C361,1217.9 355.1,1216.6 349.6,1213.9 C344.1,1211.2 339.4,1207.7 335.5,1203.2 C331.5,1198.8 328.4,1193.6 326.2,1187.8 C324,1182 322.9,1175.9 322.9,1169.6 C322.9,1163.3 324,1157.3 326.2,1151.4 C328.4,1145.6 331.5,1140.5 335.5,1136 C339.5,1131.6 344.2,1128 349.6,1125.3 C355,1122.6 361,1121.3 367.5,1121.3 C375.8,1121.3 383.4,1123.6 390.2,1128.1 C397,1132.6 402.4,1138.5 406.3,1145.7 L406.3,1049.3 C406.3,1048.4 406.7,1047.5 407.4,1046.7 C408.2,1045.9 409.1,1045.5 410.2,1045.5 L410.2,1045.5 Z M367.5,1210.1 C373,1210.1 378.1,1208.9 382.6,1206.6 C387.1,1204.3 391,1201.3 394.2,1197.6 C397.4,1193.9 399.9,1189.6 401.7,1184.7 C403.5,1179.8 404.3,1174.8 404.3,1169.6 C404.3,1164.4 403.4,1159.4 401.7,1154.5 C399.9,1149.6 397.4,1145.3 394.2,1141.6 C391,1137.9 387.1,1134.9 382.6,1132.6 C378.1,1130.3 373,1129.1 367.5,1129.1 C362.1,1129.1 357.2,1130.3 352.7,1132.6 C348.2,1134.9 344.3,1137.9 341.1,1141.6 C337.9,1145.3 335.3,1149.6 333.5,1154.5 C331.7,1159.4 330.7,1164.4 330.7,1169.6 C330.7,1174.8 331.6,1179.8 333.5,1184.7 C335.3,1189.6 337.9,1193.9 341.1,1197.6 C344.3,1201.3 348.2,1204.3 352.7,1206.6 C357.2,1208.9 362.2,1210.1 367.5,1210.1 L367.5,1210.1 Z" id="Shape" fill="#010101"></path>
<path d="M461.1,1096.5 C461.1,1098.2 460.5,1099.6 459.2,1100.8 C457.9,1102 456.4,1102.6 454.8,1102.6 C453,1102.6 451.4,1102 450.2,1100.8 C449,1099.6 448.4,1098.2 448.4,1096.5 C448.4,1094.7 449,1093.1 450.2,1091.9 C451.4,1090.7 452.9,1090.1 454.8,1090.1 C456.5,1090.1 457.9,1090.7 459.2,1091.9 C460.4,1093.1 461.1,1094.6 461.1,1096.5 L461.1,1096.5 Z M454.7,1123.6 C455.6,1123.6 456.5,1124 457.3,1124.8 C458.1,1125.6 458.5,1126.5 458.5,1127.4 L458.5,1211.6 C458.5,1212.5 458.1,1213.4 457.3,1214.2 C456.5,1215 455.6,1215.4 454.7,1215.4 C453.6,1215.4 452.7,1215 451.9,1214.2 C451.2,1213.4 450.8,1212.5 450.8,1211.6 L450.8,1127.4 C450.8,1126.5 451.2,1125.6 451.9,1124.8 C452.7,1124.1 453.6,1123.6 454.7,1123.6 L454.7,1123.6 Z" id="Shape" fill="#010101"></path>
<path d="M542.2,1123.1 C543.3,1123.1 544.2,1123.5 545,1124.3 C545.7,1125.1 546.1,1126 546.1,1126.9 C546.1,1129.5 544.8,1130.8 542.2,1130.8 L521.4,1130.8 L521.4,1212.3 C521.4,1213.2 521,1214.1 520.3,1214.9 C519.6,1215.7 518.6,1216.1 517.5,1216.1 C516.4,1216.1 515.5,1215.7 514.7,1214.9 C514,1214.1 513.6,1213.2 513.6,1212.3 L513.6,1130.8 L493.6,1130.8 C491,1130.8 489.7,1129.5 489.7,1126.9 C489.7,1126 490.1,1125.1 490.8,1124.3 C491.5,1123.5 492.5,1123.1 493.6,1123.1 L513.6,1123.1 L513.6,1093.2 C513.6,1090.6 514.9,1089.3 517.5,1089.3 C520.1,1089.3 521.4,1090.6 521.4,1093.2 L521.4,1123.1 L542.2,1123.1 L542.2,1123.1 Z" id="Shape" fill="#010101"></path>
<path d="M649.7,1122.8 C652.3,1122.8 653.6,1124.1 653.6,1126.7 C653.6,1126.9 652.9,1128.9 651.4,1132.8 C649.9,1136.7 648,1141.7 645.7,1147.9 C643.4,1154.1 640.7,1161.2 637.7,1169.1 C634.7,1177 631.5,1185.2 628.1,1193.6 C624.8,1202 621.5,1210.3 618.4,1218.4 C615.3,1226.5 612.3,1234 609.7,1240.7 C607,1247.4 604.8,1253.2 602.9,1257.9 C601.1,1262.6 599.9,1265.6 599.3,1266.9 C598.4,1268.6 597.2,1269.4 595.7,1269.4 C594.8,1269.4 593.9,1269 593.1,1268.2 C592.3,1267.4 591.9,1266.5 591.9,1265.6 C591.9,1265.2 592.4,1263.8 593.3,1261.3 C594.2,1258.8 595.3,1255.8 596.6,1252.3 C597.9,1248.8 599.4,1245 601,1240.8 C602.7,1236.6 604.2,1232.7 605.7,1228.9 C607.2,1225.1 608.5,1221.8 609.6,1219.1 C610.7,1216.3 611.4,1214.5 611.8,1213.6 C611.6,1213.4 610.6,1211.2 608.8,1207 C607,1202.8 604.7,1197.4 602,1191.1 C599.3,1184.7 596.5,1177.8 593.5,1170.5 C590.5,1163.1 587.8,1156.2 585.2,1149.9 C582.6,1143.5 580.4,1138.2 578.7,1133.8 C576.9,1129.5 576.1,1127.2 576.1,1127 C576.1,1124.4 577.4,1123.1 580,1123.1 C581.8,1123.1 583,1123.8 583.6,1125.3 L615.7,1203.7 L646.2,1125.6 C646.6,1123.6 647.8,1122.8 649.7,1122.8 L649.7,1122.8 Z" id="Shape" fill="#010101"></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
......@@ -8,7 +8,6 @@ body {
}
h1, h2, h3, h4, h5, h6 {
color:#222;
margin: 20px 0 10px;
}
......@@ -29,7 +28,6 @@ h2 {
}
h3, h4, h5, h6 {
color:#494949;
}
a {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment