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 ”;
Category: solidity
Solidity – Functions
Solidity – Functions ”; Previous Next A function is a group of reusable code which can be called anywhere in your program. This eliminates the need of writing the same code again and again. It helps programmers in writing modular codes. Functions allow a programmer to divide a big program into a number of small and manageable functions. Like any other advanced programming language, Solidity also supports all the features necessary to write modular code using functions. This section explains how to write your own functions in Solidity. Function Definition Before we use a function, we need to define it. The most common way to define a function in Solidity is by using the function keyword, followed by a unique function name, a list of parameters (that might be empty), and a statement block surrounded by curly braces. Syntax The basic syntax is shown here. function function-name(parameter-list) scope returns() { //statements } Example Try the following example. It defines a function called getResult that takes no parameters − pragma solidity ^0.5.0; contract Test { function getResult() public view returns(uint){ uint a = 1; // local variable uint b = 2; uint result = a + b; return result; } } Calling a Function To invoke a function somewhere later in the Contract, you would simply need to write the name of that function as shown in the following code. Try the following code to understand how the string works in Solidity. pragma solidity ^0.5.0; contract SolidityTest { constructor() public{ } function getResult() public view returns(string memory){ uint a = 1; uint b = 2; uint result = a + b; return integerToString(result); } function integerToString(uint _i) internal pure returns (string memory) { if (_i == 0) { return “0”; } uint j = _i; uint len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint k = len – 1; while (_i != 0) { bstr[k–] = byte(uint8(48 + _i % 10)); _i /= 10; } return string(bstr);//access local variable } } Run the above program using steps provided in Solidity First Application chapter. Output 0: string: 3 Function Parameters Till now, we have seen functions without parameters. But there is a facility to pass different parameters while calling a function. These passed parameters can be captured inside the function and any manipulation can be done over those parameters. A function can take multiple parameters separated by comma. Example Try the following example. We have used a uint2str function here. It takes one parameter. pragma solidity ^0.5.0; contract SolidityTest { constructor() public{ } function getResult() public view returns(string memory){ uint a = 1; uint b = 2; uint result = a + b; return integerToString(result); } function integerToString(uint _i) internal pure returns (string memory) { if (_i == 0) { return “0”; } uint j = _i; uint len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint k = len – 1; while (_i != 0) { bstr[k–] = byte(uint8(48 + _i % 10)); _i /= 10; } return string(bstr);//access local variable } } Run the above program using steps provided in Solidity First Application chapter. Output 0: string: 3 The return Statement A Solidity function can have an optional return statement. This is required if you want to return a value from a function. This statement should be the last statement in a function. As in above example, we are using uint2str function to return a string. In Solidity, a function can return multiple values as well. See the example below − pragma solidity ^0.5.0; contract Test { function getResult() public view returns(uint product, uint sum){ uint a = 1; // local variable uint b = 2; product = a * b; sum = a + b; //alternative return statement to return //multiple values //return(a*b, 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 – 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 – 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 ”; 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 ”;
Solidity – Function Modifiers ”; Previous Next Function Modifiers are used to modify the behaviour of a function. For example to add a prerequisite to a function. First we create a modifier with or without parameter. contract Owner { modifier onlyOwner { require(msg.sender == owner); _; } modifier costs(uint price) { if (msg.value >= price) { _; } } } The function body is inserted where the special symbol “_;” appears in the definition of a modifier. So if condition of modifier is satisfied while calling this function, the function is executed and otherwise, an exception is thrown. See the example below − pragma solidity ^0.5.0; contract Owner { address owner; constructor() public { owner = msg.sender; } modifier onlyOwner { require(msg.sender == owner); _; } modifier costs(uint price) { if (msg.value >= price) { _; } } } contract Register is Owner { mapping (address => bool) registeredAddresses; uint price; constructor(uint initialPrice) public { price = initialPrice; } function register() public payable costs(price) { registeredAddresses[msg.sender] = true; } function changePrice(uint _price) public onlyOwner { price = _price; } } Print Page Previous Next Advertisements ”;
Solidity – Enums
Solidity – Enums ”; Previous Next Enums restrict a variable to have one of only a few predefined values. The values in this enumerated list are called enums. With the use of enums it is possible to reduce the number of bugs in your code. For example, if we consider an application for a fresh juice shop, it would be possible to restrict the glass size to small, medium, and large. This would make sure that it would not allow anyone to order any size other than small, medium, or large. Example Try the following code to understand how the enum works in Solidity. pragma solidity ^0.5.0; contract test { enum FreshJuiceSize{ SMALL, MEDIUM, LARGE } FreshJuiceSize choice; FreshJuiceSize constant defaultChoice = FreshJuiceSize.MEDIUM; function setLarge() public { choice = FreshJuiceSize.LARGE; } function getChoice() public view returns (FreshJuiceSize) { return choice; } function getDefaultChoice() public pure returns (uint) { return uint(defaultChoice); } } Run the above program using steps provided in Solidity First Application chapter. First Click setLarge Button to set the value as LARGE then click getChoice to get the selected choice. Output uint8: 2 Click getDefaultChoice Button to get the default choice. Output uint256: 1 Print Page Previous Next Advertisements ”;