Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Truffle #1

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
truffle_example/build/*
98 changes: 93 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,103 @@ You can now check the balance.
[Solidity web](hhttps://ethereum.github.io/browser-solidity)


## A dev environment

### Truffle
Truffle [howtos](http://truffleframework.com/docs/getting_started/installation)

#### Installation
Install Truffle:
* `npm install -g truffle`

### A dev environment
Install test RPC client:
* [EthereumJS TestRPC](https://github.com/ethereumjs/testrpc)
* `npm install -g ethereumjs-testrpc`

`npm install -g truffle`
Run test client:
* `testrpc`

#### Init truffle project structure
Create truffle_example folder, go in and run :
* `truffle init`

this will create initial **project structure** :
* `contracts` : all contracts
* `migrations` : contract deployments
* `build` : built artifacts
* `test` : tests

#### Contract compilation
To compile contracts from `contracts` fodler :
* `truffle compile`

#### Contract deployment
Migrations are used to deploy contracts.

To run migrations from `migrations` folder:
* `truffle migrate`

#### Testing
To run all tests from `test` folder:
* `truffle test`

##### Tests in JavaScript (.es .es6 .jsx .sol)
[Mocha](http://mochajs.org/) test framework is used behind, `describe()` functions
can be replaced by `contract()` to hook-up clean contract state testing environment before each test.

##### Tests in Solidity
Less verbose than JS tests & obviously DSL is more targeted
to the very specific task than generic Mocha library.
Provides as well :
* an easy access to all deployed contracts & accounts
* assertion library
* pre/post-test hooks

#### Interaction with contracts
Reading data from network is named `call'.
Writing data is called a `transaction`.

##### Transaction
Every Tx could be an operation of:
* sending money to another account
* executing a contract's function
* registering a new contract

ALl transactions:
* Cost gas (Ether)
* Change the state of the network
* Aren't processed immediately
* Won't expose a return value (only a transaction id).

##### Call
Can execute code on the network but wothout permanent data changes!
* Are free (do not cost gas)
* Do not change the state of the network
* Are processed immediately
* Will expose a return value (hooray!)

#### Contract abstractions
Wrappers around contracts to make interactions with Ethereum contract from JS easier.
Truffle has own abstraction module : [truffle-contract](https://github.com/trufflesuite/truffle-contract)

Basically `sendCoin`, `getBalanceInEth` and `getBalance` are exposed for interactions.
All calls, transactions and fired events could be nicely executed and chaine using promises.

Contracts can be as well deployed and as a part of the test.

#### Package management ETHPM
#### ETHPM
[EHTPM](https://www.ethpm.com/) is a pakage registry.

Packages are treated asn npm depenndencies ([ethpm.json](http://truffleframework.com/docs/getting_started/packages-npm#package-management)).

Command `truffle install package@version` will install referenced package.

To pusblish see more documentation [here](http://truffleframework.com/docs/getting_started/packages-ethpm#ropsten-ropsten-ropsten)

#### npm

NPM can be used as well to publish ETH artifacts, mores infos can be found [here](http://truffleframework.com/docs/getting_started/packages-npm#package-management)

## The private net

Expand All @@ -98,10 +189,7 @@ Follow the steps from [here](https://souptacular.gitbooks.io/ethereum-tutorials-

`--datadir "./.ethereum-private" --genesis CustomGenesis.json --nodiscover --maxpeers 0`



# Questions
* qwei?
* no gas is paid to execute a contract

# Useful links
Expand Down
8 changes: 8 additions & 0 deletions truffle_example/contracts/ConvertLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pragma solidity ^0.4.4;

library ConvertLib{
function convert(uint amount,uint conversionRate) returns (uint convertedAmount)
{
return amount * conversionRate;
}
}
34 changes: 34 additions & 0 deletions truffle_example/contracts/MetaCoin.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
pragma solidity ^0.4.4;

import "./ConvertLib.sol";

// This is just a simple example of a coin-like contract.
// It is not standards compatible and cannot be expected to talk to other
// coin/token contracts. If you want to create a standards-compliant
// token, see: https://github.com/ConsenSys/Tokens. Cheers!

contract MetaCoin {
mapping (address => uint) balances;

event Transfer(address indexed _from, address indexed _to, uint256 _value);

function MetaCoin() {
balances[tx.origin] = 10000;
}

function sendCoin(address receiver, uint amount) returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[receiver] += amount;
Transfer(msg.sender, receiver, amount);
return true;
}

function getBalanceInEth(address addr) returns(uint){
return ConvertLib.convert(getBalance(addr),2);
}

function getBalance(address addr) returns(uint) {
return balances[addr];
}
}
23 changes: 23 additions & 0 deletions truffle_example/contracts/Migrations.sol
Original file line number Diff line number Diff line change
@@ -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);
}
}
5 changes: 5 additions & 0 deletions truffle_example/migrations/1_initial_migration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var Migrations = artifacts.require("./Migrations.sol");

module.exports = function(deployer) {
deployer.deploy(Migrations);
};
8 changes: 8 additions & 0 deletions truffle_example/migrations/2_deploy_contracts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
var ConvertLib = artifacts.require("./ConvertLib.sol");
var MetaCoin = artifacts.require("./MetaCoin.sol");

module.exports = function(deployer) {
deployer.deploy(ConvertLib);
deployer.link(ConvertLib, MetaCoin);
deployer.deploy(MetaCoin);
};
25 changes: 25 additions & 0 deletions truffle_example/test/TestMetacoin.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
pragma solidity ^0.4.2;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/MetaCoin.sol";

contract TestMetacoin {

function testInitialBalanceUsingDeployedContract() {
MetaCoin meta = MetaCoin(DeployedAddresses.MetaCoin());

uint expected = 10000;

Assert.equal(meta.getBalance(tx.origin), expected, "Owner should have 10000 MetaCoin initially");
}

function testInitialBalanceWithNewMetaCoin() {
MetaCoin meta = new MetaCoin();

uint expected = 10000;

Assert.equal(meta.getBalance(tx.origin), expected, "Owner should have 10000 MetaCoin initially");
}

}
63 changes: 63 additions & 0 deletions truffle_example/test/metacoin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
var MetaCoin = artifacts.require("./MetaCoin.sol");

contract('MetaCoin', function(accounts) {
it("should put 10000 MetaCoin in the first account", function() {
return MetaCoin.deployed().then(function(instance) {
return instance.getBalance.call(accounts[0]);
}).then(function(balance) {
assert.equal(balance.valueOf(), 10000, "10000 wasn't in the first account");
});
});
it("should call a function that depends on a linked library", function() {
var meta;
var metaCoinBalance;
var metaCoinEthBalance;

return MetaCoin.deployed().then(function(instance) {
meta = instance;
return meta.getBalance.call(accounts[0]);
}).then(function(outCoinBalance) {
metaCoinBalance = outCoinBalance.toNumber();
return meta.getBalanceInEth.call(accounts[0]);
}).then(function(outCoinBalanceEth) {
metaCoinEthBalance = outCoinBalanceEth.toNumber();
}).then(function() {
assert.equal(metaCoinEthBalance, 2 * metaCoinBalance, "Library function returned unexpected function, linkage may be broken");
});
});
it("should send coin correctly", function() {
var meta;

// Get initial balances of first and second account.
var account_one = accounts[0];
var account_two = accounts[1];

var account_one_starting_balance;
var account_two_starting_balance;
var account_one_ending_balance;
var account_two_ending_balance;

var amount = 10;

return MetaCoin.deployed().then(function(instance) {
meta = instance;
return meta.getBalance.call(account_one);
}).then(function(balance) {
account_one_starting_balance = balance.toNumber();
return meta.getBalance.call(account_two);
}).then(function(balance) {
account_two_starting_balance = balance.toNumber();
return meta.sendCoin(account_two, amount, {from: account_one});
}).then(function() {
return meta.getBalance.call(account_one);
}).then(function(balance) {
account_one_ending_balance = balance.toNumber();
return meta.getBalance.call(account_two);
}).then(function(balance) {
account_two_ending_balance = balance.toNumber();

assert.equal(account_one_ending_balance, account_one_starting_balance - amount, "Amount wasn't correctly taken from the sender");
assert.equal(account_two_ending_balance, account_two_starting_balance + amount, "Amount wasn't correctly sent to the receiver");
});
});
});
9 changes: 9 additions & 0 deletions truffle_example/truffle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
networks: {
development: {
host: "localhost",
port: 8545,
network_id: "*" // Match any network id
}
}
};