Solidity – Contracts

Solidity – Contracts ”; Previous Next Contract in Solidity is similar to a Class in C++. A Contract have following properties. Constructor − A special function declared with constructor keyword which will be executed once per contract and is invoked when a contract is created. State Variables − Variables per Contract to store the state of the contract. Functions − Functions per Contract which can modify the state variables to alter the state of a contract. Visibility Quantifiers Following are various visibility quantifiers for functions/state variables of a contract. external − External functions are meant to be called by other contracts. They cannot be used for internal call. To call external function within contract this.function_name() call is required. State variables cannot be marked as external. public − Public functions/ Variables can be used both externally and internally. For public state variable, Solidity automatically creates a getter function. internal − Internal functions/ Variables can only be used internally or by derived contracts. private − Private functions/ Variables can only be used internally and not even by derived contracts. Example pragma solidity ^0.5.0; contract C { //private state variable uint private data; //public state variable uint public info; //constructor constructor() public { info = 10; } //private function function increment(uint a) private pure returns(uint) { return a + 1; } //public function function updateData(uint a) public { data = a; } function getData() public view returns(uint) { return data; } function compute(uint a, uint b) internal pure returns (uint) { return a + b; } } //External Contract contract D { function readData() public returns(uint) { C c = new C(); c.updateData(7); return c.getData(); } } //Derived Contract contract E is C { uint private result; C private c; constructor() public { c = new C(); } function getComputedResult() public { result = compute(3, 5); } function getResult() public view returns(uint) { return result; } function getData() public view returns(uint) { return c.info(); } } Run the above program using steps provided in Solidity First Application chapter. Run various method of Contracts. For E.getComputedResult() followed by E.getResult() shows − Output 0: uint256: 8 Print Page Previous Next Advertisements ”;

Solidity – Constructors

Solidity – Constructors ”; Previous Next Constructor is a special function declared using constructor keyword. It is an optional funtion and is used to initialize state variables of a contract. Following are the key characteristics of a constructor. A contract can have only one constructor. A constructor code is executed once when a contract is created and it is used to initialize contract state. After a constructor code executed, the final code is deployed to blockchain. This code include public functions and code reachable through public functions. Constructor code or any internal method used only by constructor are not included in final code. A constructor can be either public or internal. A internal constructor marks the contract as abstract. In case, no constructor is defined, a default constructor is present in the contract. pragma solidity ^0.5.0; contract Test { constructor() public {} } In case, base contract have constructor with arguments, each derived contract have to pass them. Base constructor can be initialized directly using following way − pragma solidity ^0.5.0; contract Base { uint data; constructor(uint _data) public { data = _data; } } contract Derived is Base (5) { constructor() public {} } Base constructor can be initialized indirectly using following way − pragma solidity ^0.5.0; contract Base { uint data; constructor(uint _data) public { data = _data; } } contract Derived is Base { constructor(uint _info) Base(_info * _info) public {} } Direct and Indirect ways of initializing base contract constructor is not allowed. If derived contract is not passing argument(s) to base contract constructor then derived contract will become abstract. Print Page Previous Next Advertisements ”;

Function Overloading

Solidity – Function Overloading ”; Previous Next You can have multiple definitions for the same function name in the same scope. The definition of the function must differ from each other by the types and/or the number of arguments in the argument list. You cannot overload function declarations that differ only by return type. Following example shows the concept of a function overloading in Solidity. Example pragma solidity ^0.5.0; contract Test { function getSum(uint a, uint b) public pure returns(uint){ return a + b; } function getSum(uint a, uint b, uint c) public pure returns(uint){ return a + b + c; } function callSumWithTwoArguments() public pure returns(uint){ return getSum(1,2); } function callSumWithThreeArguments() public pure returns(uint){ return getSum(1,2,3); } } Run the above program using steps provided in Solidity First Application chapter. Click callSumWithTwoArguments button first and then callSumWithThreeArguments button to see the result. Output 0: uint256: 3 0: uint256: 6 Print Page Previous Next Advertisements ”;

Cryptographic Functions

Solidity – Cryptographic Functions ”; Previous Next Solidity provides inbuilt cryptographic functions as well. Following are important methods − keccak256(bytes memory) returns (bytes32) − computes the Keccak-256 hash of the input. ripemd160(bytes memory) returns (bytes20) − compute RIPEMD-160 hash of the input. sha256(bytes memory) returns (bytes32) − computes the SHA-256 hash of the input. ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address) − recover the address associated with the public key from elliptic curve signature or return zero on error. The function parameters correspond to ECDSA values of the signature: r – first 32 bytes of signature; s: second 32 bytes of signature; v: final 1 byte of signature. This method returns an address. Following example shows the usage of cryptographic function in Solidity. Example pragma solidity ^0.5.0; contract Test { function callKeccak256() public pure returns(bytes32 result){ return keccak256(“ABC”); } } Run the above program using steps provided in Solidity First Application chapter. Output 0: bytes32: result 0xe1629b9dda060bb30c7908346f6af189c16773fa148d3366701fbaa35d54f3c8 Print Page Previous Next Advertisements ”;

Solidity – Pure Functions

Solidity – Pure Functions ”; Previous Next Pure functions ensure that they not read or modify the state. A function can be declared as pure. The following statements if present in the function are considered reading the state and compiler will throw warning in such cases. Reading state variables. Accessing address(this).balance or <address>.balance. Accessing any of the special variable of block, tx, msg (msg.sig and msg.data can be read). Calling any function not marked pure. Using inline assembly that contains certain opcodes. Pure functions can use the revert() and require() functions to revert potential state changes if an error occurs. See the example below using a view function. Example pragma solidity ^0.5.0; contract Test { function getResult() public pure returns(uint product, uint sum){ uint a = 1; uint b = 2; product = a * b; sum = a + b; } } Run the above program using steps provided in Solidity First Application chapter. Output 0: uint256: product 2 1: uint256: sum 3 Print Page Previous Next Advertisements ”;

Solidity – Special Variables

Solidity – Special Variables ”; Previous Next Special variables are globally available variables and provides information about the blockchain. Following is the list of special variables − Sr.No. Special Variable & Description 1 blockhash(uint blockNumber) returns (bytes32) Hash of the given block – only works for 256 most recent, excluding current, blocks. 2 block.coinbase (address payable) Current block miner”s address. 3 block.difficulty (uint) current block difficulty. 4 block.gaslimit (uint) Current block gaslimit. 5 block.number (uint) Current block number. 6 block.timestamp Current block timestamp as seconds since unix epoch. 7 gasleft() returns (uint256) Remaining gas. 8 msg.data (bytes calldata) Complete calldata. 9 msg.sender (address payable) Sender of the message (current call). 10 msg.sig (bytes4) First four bytes of the calldata (i.e. function identifier) 11 msg.value (uint) Number of wei sent with the message. 12 now (uint) Current block timestamp (alias for block.timestamp). 13 tx.gasprice (uint) Gas price of the transaction. 14 tx.origin (address payable) Sender of the transaction (full call chain). Example Try the following code to see the use of msg, a special variable to get the sender address in Solidity. pragma solidity ^0.5.0; contract LedgerBalance { mapping(address => uint) public balances; function updateBalance(uint newBalance) public { balances[msg.sender] = newBalance; } } contract Updater { function updateBalance() public returns (uint) { LedgerBalance ledgerBalance = new LedgerBalance(); ledgerBalance.updateBalance(10); return ledgerBalance.balances(address(this)); } } Run the above program using steps provided in Solidity First Application chapter. First Click updateBalance Button to set the value as 10 then look into the logs which will show the decoded output as − Output { “0”: “uint256: 10″ } Print Page Previous Next Advertisements ”;

Solidity – Ether Units

Solidity – Ether Units ”; Previous Next In solidity we can use wei, finney, szabo or ether as a suffix to a literal to be used to convert various ether based denominations. Lowest unit is wei and 1e12 represents 1 x 1012. assert(1 wei == 1); assert(1 szabo == 1e12); assert(1 finney == 1e15); assert(1 ether == 1e18); assert(2 ether == 2000 fenny); Time Units Similar to currency, Solidity has time units where lowest unit is second and we can use seconds, minutes, hours, days and weeks as suffix to denote time. assert(1 seconds == 1); assert(1 minutes == 60 seconds); assert(1 hours == 60 minutes); assert(1 day == 24 hours); assert(1 week == 7 days); Print Page Previous Next Advertisements ”;

Solidity – Decision Making

Solidity – Decision Making ”; Previous Next While writing a program, there may be a situation when you need to adopt one out of a given set of paths. In such cases, you need to use conditional statements that allow your program to make correct decisions and perform right actions. Solidity supports conditional statements which are used to perform different actions based on different conditions. Here we will explain the if..else statement. Flow Chart of if-else The following flow chart shows how the if-else statement works. Solidity supports the following forms of if..else statement − Sr.No Statements & Description 1 if statement The if statement is the fundamental control statement that allows Solidity to make decisions and execute statements conditionally. 2 if…else statement The ”if…else” statement is the next form of control statement that allows Solidity to execute statements in a more controlled way. 3 if…else if… statement. The if…else if… statement is an advanced form of if…else that allows Solidity to make a correct decision out of several conditions. Print Page Previous Next Advertisements ”;

Solidity – Withdrawal Pattern

Solidity – Withdrawal Pattern ”; Previous Next Withdrawal pattern ensures that direct transfer call is not made which poses a security threat. Following contract is showing the insecure use of transfer call to send ether. pragma solidity ^0.5.0; contract Test { address payable public richest; uint public mostSent; constructor() public payable { richest = msg.sender; mostSent = msg.value; } function becomeRichest() public payable returns (bool) { if (msg.value > mostSent) { // Insecure practice richest.transfer(msg.value); richest = msg.sender; mostSent = msg.value; return true; } else { return false; } } } Above contract can be rendered in unusable state by causing the richest to be a contract of failing fallback function. When fallback function fails, becomeRichest() function also fails and contract will stuck forever. To mitigate this problem, we can use Withdrawal Pattern. In withdrawal pattern, we”ll reset the pending amount before each transfer. It will ensure that only caller contract fails. pragma solidity ^0.5.0; contract Test { address public richest; uint public mostSent; mapping (address => uint) pendingWithdrawals; constructor() public payable { richest = msg.sender; mostSent = msg.value; } function becomeRichest() public payable returns (bool) { if (msg.value > mostSent) { pendingWithdrawals[richest] += msg.value; richest = msg.sender; mostSent = msg.value; return true; } else { return false; } } function withdraw() public { uint amount = pendingWithdrawals[msg.sender]; pendingWithdrawals[msg.sender] = 0; msg.sender.transfer(amount); } } Print Page Previous Next Advertisements ”;

Solidity – Conversions

Solidity – Conversions ”; Previous Next Solidity allows implicit as well as explicit conversion. Solidity compiler allows implicit conversion between two data types provided no implicit conversion is possible and there is no loss of information. For example uint8 is convertible to uint16 but int8 is convertible to uint256 as int8 can contain negative value not allowed in uint256. Explicit Conversion We can explicitly convert a data type to another using constructor syntax. int8 y = -3; uint x = uint(y); //Now x = 0xfffff..fd == two complement representation of -3 in 256 bit format. Conversion to smaller type costs higher order bits. uint32 a = 0x12345678; uint16 b = uint16(a); // b = 0x5678 Conversion to higher type adds padding bits to the left. uint16 a = 0x1234; uint32 b = uint32(a); // b = 0x00001234 Conversion to smaller byte costs higher order data. bytes2 a = 0x1234; bytes1 b = bytes1(a); // b = 0x12 Conversion to larger byte add padding bits to the right. bytes2 a = 0x1234; bytes4 b = bytes4(a); // b = 0x12340000 Conversion between fixed size bytes and int is only possible when both are of same size. bytes2 a = 0x1234; uint32 b = uint16(a); // b = 0x00001234 uint32 c = uint32(bytes4(a)); // c = 0x12340000 uint8 d = uint8(uint16(a)); // d = 0x34 uint8 e = uint8(bytes1(a)); // e = 0x12 Hexadecimal numbers can be assigned to any integer type if no truncation is needed. uint8 a = 12; // no error uint32 b = 1234; // no error uint16 c = 0x123456; // error, as truncation required to 0x3456 Print Page Previous Next Advertisements ”;