diff options
| -rw-r--r-- | solidity.html.markdown | 226 | 
1 files changed, 145 insertions, 81 deletions
diff --git a/solidity.html.markdown b/solidity.html.markdown index 88ccd817..0fa1fddc 100644 --- a/solidity.html.markdown +++ b/solidity.html.markdown @@ -14,7 +14,7 @@ As Solidity and Ethereum are under active development, experimental or beta feat  ```javascript  // Let's start with a simple Bank contract, before diving into to the key components of the language -// START EXAMPLE +// ** START EXAMPLE **  // Start with a Natspec comment (the three slashes) that can be used  // for documentation - and as descriptive data for UI elements  /// @title A simple deposit/withdrawal bank built on Bitcoin @@ -22,31 +22,30 @@ As Solidity and Ethereum are under active development, experimental or beta feat  // All contracts are declared and named (in CamelCase)  // They are similar to 'class' in other languages (and allow capabilities like inheritance)  contract AcmeBank { -    // Declare state variables outside a function,  +    // Declare state variables outside a function,      // these are persistent throughout the life of the contract      // a dictionary that maps addresses to balances -    mapping (address => uint) balances;  +    mapping (address => uint) balances; + +    // the 'public' makes 'owner' externally readable by users or contracts +    // (but not writeable) - +    address public owner; -    // the 'public' makes 'owner' externally readable by users or contracts  -    // (but not writeable), the 'constant' means this value to be  -    // changed after initialization -    address public owner;  -          // Constructor, can receive one or many variables here      function AcmeBank() { -      // msg is a default variable that provides both the  +      // msg is a default variable that provides both the        // contract messager's address and amount        owner = msg.sender; // msg.sender refers to the address of the contract creator      } -   -    function deposit(uint balance) { + +    function deposit(uint balance) public {          balances[msg.sender] += msg.value; // no need for "this." or "self." in front of the state variable          return balances[msg.sender]; // msg.sender refers to the contract caller      } -    function withdraw(uint withdrawAmount) returns (uint remainingBalance) { +    function withdraw(uint withdrawAmount) public returns (uint remainingBalance) {        if(balances[msg.sender] >= withdrawAmount) {          balances[msg.sender] -= withdrawAmount; @@ -58,8 +57,9 @@ contract AcmeBank {        }      } -    // It's good practice to have a remove function, which disables this contract - but does mean that users have to trust the owner -    function remove () { +    // It's good practice to have a remove function, which disables this +    // contract - but does mean that users have to trust the owner +    function remove() {        if(msg.sender == owner) { // Only let the contract creator do this          suicide(owner); // suicide makes this contract inactive, and returns funds to the owner        } @@ -71,29 +71,35 @@ contract AcmeBank {      }      // Fallback function -    // This function is called if invalid data is sent or ether without data;  +    // The fallback function is called if none of the other functions matches the given function identifier. +    // It is often meant to be called when invalid data is sent or ether without data.      // Added so that ether sent to this contract is reverted if the contract fails      // otherwise, the sender loses their money; you should add this in most contracts      function () { throw; }  } -// END EXAMPLE +// ** END EXAMPLE **  // Now let's go through the basics of Solidity -// 1. DATA TYPES +// 1. DATA TYPES AND ASSOCIATED METHOD  // uint is the data type typically used for currency (there are no doubles  //  or floats) and for dates -uint x;  -int constant a = 8; // int of 256 bits, cannot be changed after instantiation +uint x; + + +// with 'constant', the compiler replaces each occurence with the acutal value +// int of 256 bits, cannot be changed after instantiation +int constant a = 8; +int256 constant a = 8; // same effect as line above, here the 256 is explict + +// For both int and uint, you can explicitly set space in steps of 8 +// e.g., int8, int16  uint8 b;  int64 c; -// int256 is same as int -// For both int and uint, you can explicitly set space in steps of 8,  -// e.g., int8, int16  uint248 e;  // Type casting -int x = int(b) +int x = int(b);  bool b = true; // or do 'var b = true;' for inferred typing @@ -115,21 +121,22 @@ bytes m; // A special array, same as byte[] (but packed tightly)  string n = 'hello';  // Type inference -// var does inferred typing based on first assignment,  +// var does inferred typing based on first assignment,  // can't be used in functions parameters  var a = true; -// there are edge cases where inference leads to a value being set (e.g., an uint 8)  +// there are edge cases where inference leads to a value being set (e.g., an uint 8)  // that is different from what the user wanted (uint16), so use carefully  // by default, all values are set to 0 on instantiation -// Delete can be called on most types, and will set the values to 0 +// Delete can be called on most types, and will set the values to 0 by assignment  uint x = 5;  delete(x); // x is now 0  // 2. DATA STRUCTURES  // Arrays -bytes32[] names; +bytes32[5] nicknames; // static array +bytes32[] names; // dynamic array  uint newLength = names.push("John"); // adding returns new length of the array  // Length  names.length; // get length @@ -153,13 +160,13 @@ delete(balances); // deletes all elements  // Unlike languages like Javascript, you cannot iterate through all elements in  // a map, without knowing the source keys -// Structs and enums  +// Structs and enums    struct Bank { // note the capital        address owner;        uint balance;    }  Bank b = Bank({ -  owner: msg.sender,  +  owner: msg.sender,    balance: 5  });  delete(b); // set all values to 0, except any mappings @@ -168,29 +175,39 @@ delete(b); // set all values to 0, except any mappings  enum State { Created, Locked, Inactive };  State public state; // Declare variable from enum  state = State.Created; +// enums can be explicitly converted to ints -// 3. Variables of note -// storage - A persistent storage hash (does not need to be declared) -storage['abc'] = 'def'; // maps 256 bit words to 256 bit words +// Data locations: Memory vs. storage - all complex types (arrays, structs) have a data location +// 'memory' does not persist, 'storage' does +// Default is 'storage' for local and state variables; 'memory' for function parameters -// tx - This transaction -tx.origin // address, sender of the transaction -tx.gasprice // uint, gas price of the transaction +// 3. Variables of note +// ** this ** +this; // the address of the current contract +// 'balance' often used at the end of a contracts life to send the +// remaining balance to a party +this.balance; +this.someFunction(); // calls a function externally (via a message call, not via an internal jump) -// msg - The current message received by the contract +// ** msg - The current message received by the contract ** **  msg.sender; // address, The address of the sender  msg.value; // uint, The amount of gas provided to this contract in wei -msg.data // bytes, complete call data +msg.data; // bytes, complete call data +msg.gas; // remaining gas -// balance of the current contract (both contract and external accounts  -// have balances) - often used at the end of a contracts life to send the  -// remaining balance to a party -this.balance  -// block +// ** tx - This transaction ** +tx.origin; // address, sender of the transaction +tx.gasprice; // uint, gas price of the transaction + +// ** block - Information about the current block **  now // uint, current time, alias for block.timestamp -block.number // uint, current block number -block.difficulty // uint, current block difficulty -block.blockhash(1) // returns bytes32, only provides for most recent 256 block +block.number; // uint, current block number +block.difficulty; // uint, current block difficulty +block.blockhash(1); // returns bytes32, only provides for most recent 256 blocks +block.gasLimit(); + +// ** storage - A persistent storage hash (does not need to be declared) ** +storage['abc'] = 'def'; // maps 256 bit words to 256 bit words  // 4. FUNCTIONS AND MORE  // A. Functions @@ -236,13 +253,13 @@ function b() {  // B. Events  // Events are an easy way to notify external listeners that something changed -// You typically decalre them after your contract parameters +// You typically declare them after your contract parameters  event Sent(address from, address to, uint amount);  // You then call it in a function, when you want to trigger it  sent(from, to, amount); -// For an external party (a contract or external entity), to watch  +// For an external party (a contract or external entity), to watch  // for an event, you write the following:  Coin.Sent().watch({}, '', function(error, result) {      if (!error) { @@ -254,53 +271,89 @@ Coin.Sent().watch({}, '', function(error, result) {              "Receiver: " + Coin.balances.call(result.args.to));      }  } -// This is a common paradigm for one contract to depend on another (e.g., a  +// This is a common paradigm for one contract to depend on another (e.g., a  // contract that depends on the current exchange rate provided by another  // contract)  // C. Modifiers -// Modifiers let you validate inputs to functions -// The '_' (underscore) must be included, and is an indicator that the  +// Modifiers let you validate inputs to functions such as a minimal balance or user authentication +// It's similar to a guard clause in other languages + +// The '_' (underscore) must be included as the last line in the function body, and is an indicator that the  // function being called should be placed there  modifier onlyBefore(uint _time) { if (now >= _time) throw; _ }  // You can then append it right after the function declaration -function test() -  onlyBefore() -{ - +function changeOwner(newOwner) +  onlyBefore(someTime) +  { +  owner = newOwner;  }  // 5. BRANCHING AND LOOPS  // All basic logic blocks work - including if/else, for, while, break, continue, return  // switch is not provided -// Syntax is the same as javascript, but there is no type conversion from  -// non-boolean to boolean -// 6. CALLING AN EXTERNAL CONTRACT +// Syntax is the same as javascript, but there is no type conversion from +// non-boolean to boolean, so comparison operators must be used to get the boolean value + +// 6. OBJECTS/CONTRACTS +// A. Calling an external contract  contract infoFeed {    function info() returns (uint ret) { return 42; }  }  contract Consumer {    InfoFeed feed; // create a variable that will point to a contract on the blockchain -  function setFeed(address addr) {  + +  // Set feed to an existing contract +  function setFeed(address addr) {      // Link to the contract by creating on the address -    feed = InfoFeed(addr);  +    feed = InfoFeed(addr);    } -  function callFeed() {  -    // T final parentheses call the contract, optionally adding  + +  // Set feed based to a new instance of the contract +  function createNewFeed() { +    feed = new InfoFeed(); +  } + +  function callFeed() { +    // T final parentheses call the contract, optionally adding      // custom value or gas numbers      feed.info.value(10).gas(800)();    }  } +// B. Inheritance + +// Order matters, last inherited contract (i.e., 'def') can override parts of the previously +// inherited contracts +contact MyContract is abc, def("a custom argument to def") { + +// Override function + +  function z() { +    if (msg.sender == owner) { +      def.z(); // call overridden function +    } +  } + +  }; + +// C. Import + +import "filename"; +import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol"; + +// Importing is under active development and will change +// Importing cannot currently be done at the command line +  // 7. CONTRACT DESIGN PATTERNS  // A. Obfuscation -// Remember that all variables are publicly viewable on the blockchain, so  +// Remember that all variables are publicly viewable on the blockchain, so  // anything that needs some privacy needs to be obfuscated (e.g., hashed)  // B. Throwing @@ -317,26 +370,34 @@ if (!addr.send(123)) {  // Suicide  suicide(SOME_ADDRESS); // suicide the current contract, sending funds to the address (often the creator) +// This is a common pattern that lets the owner end the contract +function remove() { +  if(msg.sender == owner) { // Only let the contract creator do this +    suicide(owner); // suicide makes this contract inactive, and returns funds to the owner +  } +} +  // D. Storage optimization -// Reading and writing can be expensive, as data needs to be stored in the  -// blockchain forever - this encourages smart ways to use memory (eventually,  -// compilation may better handle this, but for now there are benefits to  +// Reading and writing can be expensive, as data needs to be stored in the +// blockchain forever - this encourages smart ways to use memory (eventually, +// compilation may better handle this, but for now there are benefits to  // planning your data structures)  // *** EXAMPLE: Let's do a more complex example *** + +// ** START EXAMPLE **  // [TODO: Decide what a more complex example looks like, needs a few characteristics:  //   - has a 'constant' state variable -//   - has a state machine (uses modifier) +//   - has a state machine (and uses modifier)  //   - sends money to an address  //   - gets information from another contract (we'll show code for both contracts)  //   - Shows inheritance  //   - show variables being passed in on instantiation (and guard code to throw if variables not provided) -//   - Shows the swapping out of a contract +//   - Shows the swapping out of a contract address  //   Ideas:  //     - crowdfunding?  //     - Peer to peer insurance  // ] -  // *** END EXAMPLE ***  // Some final points @@ -353,7 +414,7 @@ uint a = 1 finney; // 1 ether = 1000 finney  1 minutes == 60 seconds -// You typically multiply a variable times the unit, as these units are not  +// You typically multiply a variable times the unit, as these units are not  // directly stored in a variable  uint x = 5;  (x * 1 days); // 5 days @@ -366,22 +427,22 @@ sha3("ab", "cd");  ripemd160("abc");  sha256("def"); -// These are natspec comments, when a user is asked to confirm a transaction -///  -/** */ +// 8. COMMON MISTAKES/MISCONCEPTIONS +// A few common mistakes and misconceptions: -// 8. COMMON MISTAKES -// A few common mistakes -// You cannot restrict a human or computer from reading the content of  +// A. You cannot restrict a human or computer from reading the content of  // your transaction or a transaction's state -// All data to the start of time is stored in the blockchain, so you and  -// anyone can observe all previous data states +// All data to the start of time is stored in the blockchain, so you and +// anyone can observe all previous data stats -// 9. TESTING +// When you don't specify public on a variable, you are indicating that other *contracts* can't +// read the data - but any person can still read the data -// 10. STYLE NOTES -// Use 4 spaces for indentation  +// TODO + +// 9. STYLE NOTES +// Use 4 spaces for indentation  // (Python's PEP8 is used as the baseline style guide, including its general philosophy)  ``` @@ -391,4 +452,7 @@ sha256("def");  - [Browser-based Solidity Editor](http://chriseth.github.io/browser-solidity/)  - [Gitter Chat room](https://gitter.im/ethereum/go-ethereum) -Feel free to send a pull request with any edits - or email nemild -/at-/ gmail
\ No newline at end of file +## Information purposefully excluded +- Libraries + +Feel free to send a pull request with any edits - or email nemild -/at-/ gmail  | 
