53
ethereum smart contract 林林林

Solidity Simple Tutorial EN

Embed Size (px)

Citation preview

Page 1: Solidity Simple Tutorial EN

ethereum smart contract

林修平

Page 2: Solidity Simple Tutorial EN

online compiler

• online compiler :https://ethereum.github.io/browser-solidity/

Page 3: Solidity Simple Tutorial EN

MANUAL COMPILE(using geth)

• connect to console

• set up a chain

• connect to main chain: go-ethereum/build/bin/geth console

• connect to testnet: go-ethereum/build/bin/geth --testnet console

• build a private net: go-ethereum/build/bin/geth --datadir “your_directory" --rpc --rpcport port --rpccorsdomain "*" --port "30303" --nodiscover --ipcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" --rpcapi "db,eth,net,web3" --autodag --networkid number --nat "any" console

Page 4: Solidity Simple Tutorial EN

MANUAL COMPILE(using geth)

• in console

• var contractABI = web3.eth.contract([{contractABI}]);

• var contract123 = contractABI.new( parameters, {from: address, data: bytecode, gas: gas }, callback_function)

Page 5: Solidity Simple Tutorial EN

Quick Intro

Page 6: Solidity Simple Tutorial EN

• price unit: ether

• address: you can withdraw from or save ether to it.

• it can represent an user account

• no code

• or represent a contract

• tied with a code

• NOTE: same code on different address is different contract

• transaction:• send ether

• or to execute function in a contract

• or both

Quick Intro

Page 7: Solidity Simple Tutorial EN

• contract: comprised of state and function

• state: used by user to keep information regarding the contract

• function: change state of a contract

• NOTE: Ethereum discourage users from using state to preserve information, so it cost a lot of gas to either create or change the state.

• WHY? Since every node(miner) needs to keep a full copy of the blockchain, they have to be compensated for storage cost of every contract.

• gas

• every function comprised of many operations and there’s a price to every type of operation

• there’s a fixed amount of gas cost to function you design and you have to pay for it when you want to execute a function

• you can decide how much ether you want to pay per gas and that becomes transaction fee needed for this execution

Quick Intro

Page 8: Solidity Simple Tutorial EN

• If you are on a public chain, every storage cost matters.

• But what if you are on a private chain?

• you can have ether as many as you want so you don’t need to worry about transaction fee

• but does it mean that you can use as many storage as you want?

• YES! but still, the costs of storing these states are to be taken by all nodes in your private chain

Quick Intro

Page 9: Solidity Simple Tutorial EN

How it work

Page 10: Solidity Simple Tutorial EN

• state• function: operate on states

• design logic: use functions to make your contract work

How it work

Page 11: Solidity Simple Tutorial EN

How it work

contract Count123{uint counts(0);function incre(){

counts = count + 1;

}}

Transaction(Deploy)

Page 12: Solidity Simple Tutorial EN

How it work

contract Count123{uint counts(0);function incre(){

counts = count + 1;

}}

Page 13: Solidity Simple Tutorial EN

How it work

Transaction(Invoke)

Count123.incre()contract Count123{

uint counts(0);function incre(){

counts = count + 1;

}}

Page 14: Solidity Simple Tutorial EN

let’s take slock.it for example and write a simple bike renting contract!

slock.it

How it work

Page 15: Solidity Simple Tutorial EN

state declaration

Page 16: Solidity Simple Tutorial EN

state declaration

contract bikeRenting {

address public owner;

address public currentRenter;

uint public expireTime;

}

Page 17: Solidity Simple Tutorial EN

• type , visibility , variable_name

state declaration

contract bikeRenting {

address public owner;

address public currentRenter;

uint public expireTime;

}

Page 18: Solidity Simple Tutorial EN

• type , visibility , variable_name

• type : bool, int, uint, address, mapping, bytes, string, struct

• visibility : public or private(default)

• public: accessible externally(declare in your contract) uint public totalCount = 3;(access in a console) mycontract.totalCount(); //3(access from other contract) thatcontract.totalCount() //3

• variable_name

state declaration

Page 19: Solidity Simple Tutorial EN

• Array in solidity :

• address[] owners; address[3] threeOwners;

• push item into array: owners.push(address)

• delete item: delete owners[2]

• pitfall: only changes the value of specified item to zero instead of erase the item

state declaration

Page 20: Solidity Simple Tutorial EN

• mapping :

• mapping(typeA => typeB) variable_name;

• example

• declare a mapping:

• mapping(address => uint) deposits;

• map address 0x123456789abcdef to integer 10:

• deposits[0x123456789abcdef] = 10;

• uninitialized or undeclared values are zero instead of NULL

• NOTE: there’s no NULL in Solidity

state declaration

Page 21: Solidity Simple Tutorial EN

• Units and Globally available variables

• Ether unit: ether、 finney、wei

• time unit: seconds、weeks、 years、 now

• now: present time

• more specifically, the time when this block is mined, i.e, the time_stamp parameter in the block header

state declaration

Page 22: Solidity Simple Tutorial EN

• Special variables and functions

• msg: information regarding this transaction

• msg.sender: address who send the transaction

• msg.value: value sent with the transaction

• address related functions

• address.balance

• address.send(amount): send ether to address

state declaration

Page 23: Solidity Simple Tutorial EN

• Special variables and functions

• throw

• reverts all changes made so far by the underlying transaction

• confiscate all gas provided by underlying transaction

state declaration

Page 24: Solidity Simple Tutorial EN

initialization

Page 25: Solidity Simple Tutorial EN

initialization

contract bikeRenting {address public owner;address public currentRenter;uint public expireTime;uint public unitPrice;

function bikeRenting(uint _unitPrice){

owner = msg.sender;

currentRenter = 0x0;

expireTime = now;

unitPrice = _unitPrice;

}

}

Page 26: Solidity Simple Tutorial EN

• constructor function

• it’s name is exactly the same as contract’s

• executed when the contract is been deployed to blockchain

• executed only once

• not necessary

initialization

Page 27: Solidity Simple Tutorial EN

function

Page 28: Solidity Simple Tutorial EN

contract bikeRenting {address public owner;address public currentRenter;uint public expireTime;uint public unitPrice;function bikeRenting(uint _unitPrice){

…}

function rent() payable returns(bool){if(currentRenter != 0x0) return false;else{

if( (msg.value/1 ether) / unitPrice < 1) return false; else {

expireTime = now + 15 minutes * (msg.value/1 ether)/unitPrice; currentRenter = msg.sender; rentingRecord(msg.sender, now, (msg.value/1 ether)/unitPrice);

}}

}

}

check if it’s been rented

how much time you getfor one unit

check if paid more than a unit price

functionhow many ether per unit

Page 29: Solidity Simple Tutorial EN

function functionName(parameter1, parameter2, …) returns(type) {

}

• declare parameters: bool a, uint b, address c, …

• returns:

• not necessary

• function foo() returns(uint, address, bool) { … return (1, 0x0, true);}

function

Page 30: Solidity Simple Tutorial EN

• visibility of a function

• public(default)

• private: only accessible by this contract

• internal: only accessible by this contract and contracts inherited from this one

• external: exactly the opposite of internal

• payable:

• decide if people can send ether while they execute this function, in other words, if you create a transaction to execute this function, you will be able to send the transaction along with some ether only if this function is a payable function

function

Page 31: Solidity Simple Tutorial EN

contract bikeRenting {address public owner;address public currentRenter;uint public expireTime;uint public unitPrice;function bikeRenting(uint _unitPrice){…}function rent() payable returns(bool){…}

function isInUse(bool ifWantToRent) payable returns(bool){if( expireTime > now ) return true;else{

currentRenter = 0x0;if( ifWantToRent == true) rent();

}}

}

this function checks if the bike is rented

ifWantToRent is a parameter sent byperson who execute this transaction,

indicating if he/she wants to rent this bike

not expired yet, it is rented

function

Page 32: Solidity Simple Tutorial EN

function

• we have to make sure person who executes isInUse function has the priority to rent if the bike is available because he/she pays transaction fee to execute this function

• why we need someone else to check if the bike is been rented or not?• because a smart contract is not a robot, it won’t execute a

command actively• it won’t lock the bike itself even time is up, it needs to be triggered

• but if there are more than two people execute the same function in the same time, there’s no guarantee on the order of the execution

• so we have to make sure person who gets to execute isInUse function first will have the priority to rent the bike because he/she pays for this execution

Page 33: Solidity Simple Tutorial EN

contract bikeRenting {address public owner;address public currentRenter;uint public expireTime;uint public unitPrice;function bikeRenting(uint _unitPrice){…}function rent() payable returns(bool){…}function isInUse(bool ifWantToRent) payable returns(bool){…}

function collectMoney() {if( msg.sender == owner){

owner.send(this.balance) ;}

}

}

make sure only owner can execute this function

function

Page 34: Solidity Simple Tutorial EN

privilege

Page 35: Solidity Simple Tutorial EN

privilege

• there’s no built-in mechanism to restrict execution privilege, you have to check if person who executes the function has the right to

• HOW?

• using msg.sender to compare with addresses which have the right to execute

function collectMoney() {

if(msg.sender == owner){

}

}

Page 36: Solidity Simple Tutorial EN

repetitive actions

Page 37: Solidity Simple Tutorial EN

• modifier

• attach to modifier: function bar() foo1() {…}

• attach to multiple modifiers: function bar() foo1() foo2() foo3(){…}

repetitive actions

modifier foo1 { do_something _; or_do_something_here}

a place holder for code of attaching function

Page 38: Solidity Simple Tutorial EN

contract foo1 {

modifier ownerCheck { if(msg.sender == owner ) _;}function collectMoney() ownerCheck {

owner.send(this.balance) ;}

}

repetitive actions

Page 39: Solidity Simple Tutorial EN

contract modifierTest{modifier foo1(){

foo1before;_;foo1after;

}modifier foo2(){

foo2before;_;foo2after;

}function bar() foo1() foo2() {

bar;}

}

repetitive actions

execution order:foo1beforefoo2beforebarfoo2afterfoo1after

Page 40: Solidity Simple Tutorial EN

contract creation in a contract

Page 41: Solidity Simple Tutorial EN

contract creation in a contract

contract foo{ … }

address newFooAddr = new foo();

• returns an address

foo foo1 = foo(newFooAddr);

• returns a contract

• NOTE: contract creation usually cost a lot of gas so remember to supply enough gas if you execute a function which creates new contracts

Page 42: Solidity Simple Tutorial EN

fallback function

Page 43: Solidity Simple Tutorial EN

fallback function

• it’s executed only when someone executes a function not existed in the contract or someone simply sends some ether to this contract

• not necessary

• pitfall:

• person who owns this contract gets to decide what to do in a fallback function

• if you simply sends some ether to this contract, you also have to pay for the execution of fallback function if there is one

function () {…

} function with no name

Page 44: Solidity Simple Tutorial EN

pitfalls

Page 45: Solidity Simple Tutorial EN

pitfalls

• throw when address.send() fails

• throw will revert all changes and confiscate all gas even if you are halfway there

for(uint i=0; i<investorsCount; i++) {

if( inverstors[i].send(100) == false )

throw;}

Page 46: Solidity Simple Tutorial EN

pitfalls

• throw when address.send() fails

• why address.send() fail?

• 1. out of gas

• supply enough gas

• 2. callstack

• 1024 layer

Page 47: Solidity Simple Tutorial EN

pitfalls

• throw when address.send() fails

• mitigation: use a withdraw pattern

• still, this solution leaves the problems mentioned to the msg sender

function withdraw(amount) {if( balances[msg.sender] >=

amount ) {msg.sender.send(amount);

balances[msg.sender] -= amount;}

}

Page 48: Solidity Simple Tutorial EN

pitfalls

• shared state between external call and external callable functionsfunction extCall() {

…external_call();…if(shared_state) {

…}…

}

function extCallable(){do_something_on_shared_state…

}

execute function ofsome other contract

then that function executethis function

Page 49: Solidity Simple Tutorial EN

pitfalls

• state corruption

• 1. sum of sizes of 1st and 2nd state variables are less than 256 bytes

• 2. first variable is not a signed interger or bytesXX typefunction extCall() {

uint32 a;uint32 b;function run() returns(uint32){

a--;return b;

}}

fixed after compiler version 0.4.4

Page 50: Solidity Simple Tutorial EN

Misc

• selfdestruct(recipient)

• terminate the contract, destroy code and storage, then transfer the remaining ether to recipient

• event: writes data into transaction receipt

• example: event paymentRecord(address indexed buyer, uint value)

• indexed: write data into topics field

• if data is more than 32 bytes, hash of data is written into topics instead

• transaction receipt

• data

• topics: can be used as a condition filter

Page 51: Solidity Simple Tutorial EN

Misc

Page 52: Solidity Simple Tutorial EN

• contract inheritance : contract Final is most-base-like, …, most-derived {…}

Misc

Page 53: Solidity Simple Tutorial EN

tips

• use delete on array to delete all elements

• --vmdebug, --verbosity

• --targetgaslimit