How to handle floating-point numbers in Ethereum smart contracts? - ethereum

recently, I’ve been learning about the development of Ethereum smart contracts. I have a question about the following code; the result obtained by the “a” method is 4. This result is the same as my common sense understanding because, in the floating-point processing, the corresponding floating-point number will be intercepted when running. However, when I call the method “b”, the result is 5. I don't understand this result very well. Is it because the compiler has optimised during the compilation process to calculate the outcome directly and store it? Thanks a lot, guys.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Test {
uint constant c = 5;
function a() public pure returns(uint){
return c/2 + c/2;
}
function b() public pure returns(uint){
return 5/2 + 5/2;
}
}

It seems that compiler optimize the return 5/2 + 5/2; line. In assembly output, after compiling with solc-v0.8.13 --asm --optimize-run=100000, there are following lines:
/* "Test.sol":215:224 5/2 + 5/2 */
0x05
/* "Test.sol":208:224 return 5/2 + 5/2 */
swap1
pop
What indicates that 0x05 value is directly returned from function call.
In function a the integer division is rounded down, so returned value is 0x04. Compiler doesn't optimize this line, even though it operates on constant and literals, and allows to run integer division on EVM.
Worth mentioning is fact, that solidity is a language under continous development. So it's possible, that future compiler version will optimize code in such a way that functions in this example will give both the same results.

Related

Why does gas cost depends on function input?

I was testing this code using Remix. I was wondering why the execution cost of the function (in gas) depends on the input x. The cost seems to increase in multiples of 12 as the value of x increases. I haven't found a pattern.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;
contract Example{
function test (uint x) external pure returns(bool z) {
if(x > 0)
z=true;
else
z=false;
}
}
https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a0-0-intrinsic-gas
The bytes sent to the contract indeed decides the gas cost as can be seen from the link.
gas_cost += 4 * bytes_zero: gas added to base cost for every zero byte of memory data
gas_cost += 16 * bytes_nonzero: gas added to base cost for every nonzero byte of memory data
so if you send 0x0001 or 0x0010 it will cost the same amount of gas. But if you send 0x0011 it will cost 12(16-4) gas more than the previous case.
Gas is charged in three scenarios
The computation of an operation
For contract creation or message calls
An increase in the use of memory. Function args and local variables in functions are memory data. In Ethereum Solidity, what is the purpose of the "memory" keyword?

Standard Common Practice Method in Solidity to perfrom any type of division?

I am trying to do the following calculation with solidity:
3,000 / 45,000,000 = 0.000067 with the following method:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
function divide(uint _num1, uint _num2) public pure returns(uint _result) {
return (_num1 /_num2 );
}
But obviously, I am getting the results as zero.
I am aware that solidity for transactions uses 18 decimal points (using Wei), however, I could not find in the replay to all the previous questions regarding the decimals in solidity how to do it for regular numbers, or regular calculations. Also most of the time it does not even work with transactions.
What is the actual commonly used standard practice method to do "ANY" division from "ANY" number, regardless being for Ether, Tokens, or regular calculations?
I mean a method that would work for 3 / 100 just as well as 2.5 / 3.7?
Floating-point arithmetics are not supported in Solidity however you can use fixed-point arithmetics considering that you have 18 points of decimals if you use uint256.

Are there more complex functions to call from within Solidity (Smart Contracts/Ethereum)?

I am wondering besides these below mathematical expressions are there any other functions available to call inside a smart contract? Like math functions, like pi, sin, cosine, random() etc?
I am wondering if one can write smart contracts that require a little more than just basic arithmetic.
Below Image is taken from this page:
https://docs.soliditylang.org/en/develop/cheatsheet.html#function-visibility-specifiers
Solidity doesn't natively support storing floating point numbers both in storage and memory, probably because the EVM (Ethereum Virtual Machine; underlying layer) doesn't support it.
It allows working with them to some extent such as uint two = 3 / 1.5;.
So most floating point operations are usually done by defining a uint256 (256bit unsigned integer) number and another number defining the decimal length.
For example token contracts generally use 18 decimal places:
uint8 decimals = 18;
uint256 one = 1000000000000000000;
uint256 half = 500000000000000000;
There are some third-party libraries for calculating trigonometric functions (link), working with date time (link) and other use cases, but the native language currently doesn't support many of these features.
As for generating random numbers: No native function, but you can calculate a modulo of some pseudo-random variables such as block.hash and block.timestamp. Mind that these values can be (to some extent) manipulated by a miner publishing the currently mined block.
It's not recommended to use them in apps that work with money (pretty much most of smart contracts), because if the incentive is big enough, there can be a dishonest miner who can use the advantage of knowing the values before rest of the network and being able to modify them to some extent to their own benefit.
Example:
// a dishonest miner can publish a block with such params,
// that will result in the condition being true
// and their own tx to be the first one in the block that executes this function
function win10ETH() external {
if (uint256(blockhash(block.number)) % 12345 == 0) {
payable(msg.sender).transfer(10 ether);
}
}
If you need a random number that is not determinable by a miner, you can use the oracle approach, where an external app (called oracle) listens to transactions in a predefined format (generally also from&to specific addresses), performs an off-chain action (such as generating a random number, retrieving a google search result, or basically anything) and afterwards sends another transaction to your contract, containing the result of the off-chain action.

c++ templates generation times

Hi everyone I've a question about templates in c++.
I would like to explain what I wonder via an example. Lets max() will be our template function:
template <typename Type>
Type max(Type tX, Type tY)
{
return (tX > tY) ? tX : tY;
}
Now, when i call this max in my main, for each call does the compiler generate the function
and replaces the templates type with actual types ?
I mean;
int main()
{
int result1,result2;
float result3;
result1=max(3,5);
result2=max(10,12);
result3=max(4.5,12.2);
return 0;
}
In here max will be copied 3 times and replaced its parameters or something else ? Is there anyone who can help me ? Thanks in advance.
My understanding is that a compiler typically resolves templates once per data type per compilation unit. And the linker does clever stuff to stop code bloat: i.e. multiple copies of the same function across all compilation units are condensed into 1. The early Microsoft C++ linkers didn't bother doing any such thing and the generated code was large.
In your example I would expect two functions to be generated; one with two arguments and one with four.
Ah - I see you've edited the post to have two floating point parameters in the last case rather than four integral types.

Compile time checking in Design by Contract?

I read that compiler can enforce dbc at compile time.. How does it do it?
As far as I know, the most powerful static DbC language so far is Spec# by Microsoft Research. It uses a powerful static analysis tool called Boogie which in turn uses a powerful Theorem Prover / Constraint Solver called Z3 to prove either the fulfillment or violation of contracts at design time.
If the Theorem Prover can prove that a contract will always be violated, that's a compile error. If the Theorem Prover can prove that a contract will never be violated, that's an optimization: the contract checks are removed from the final DLL.
As Charlie Martin points out, proving contracts in general is equivalent to solving the Halting Problem and thus not possible. So, there will be a lot of cases, where the Theorem Prover can neither prove nor disprove the contract. In that case, a runtime check is emitted, just like in other, less powerful contract systems.
Please note that Spec# is no longer being developed. The contract engine has been extracted into a library, called Code Contracts for .NET, which will be a part of .NET 4.0 / Visual Studio 2010. However, there will be no language support for contracts.
The compiler can use static analysis to look at your program and determine whether it does the right thing. As a simple example, the following code might try to take the square root of a negative number (C++):
double x;
cin >> x;
cout << sqrt(x) << endl;
If the compiler knows that sqrt should never be called with a negative number, it could flag this as a problem because it knows that reading from user input could return a negative number. On the other hand, if you do this:
double x;
cin >> x;
if (x >= 0) {
cout << sqrt(x) << endl;
} else {
cout << "Can't take square root of negative number" << endl;
}
then the compiler can tell that this code won't ever call sqrt with a negative number.
Design by Contract is a very abstract term, since there can be many specification formalisms with different powers of expression. In addition, there is at present a limit to the abilities of static analysis to check and enforce specifications. It's one of the most active academic and industrial research fields in computer science.
In practice, it is likely that you will use some subset of contracts and checking, and that depends on the language that you are using and on the plugins or programs you install.
In general, static analysis tries to build a model of the contract, and a model of the actual program, and compare them. For example, if the contract doesn't let you invoke a function when an object is in state S, it will try to determine whether in any invocation sequence you could end up in state S.
Which compiler and what language? Eiffel can do it to some extent. But remember that completely enforcing design-by-contract would mean being able to solve the Halting Problem (proof: assume you have a compiler that could do it. Then the compiler would have to be able to identify an arbitrary function with a true exit condition that can't achieve the exit condition because of an infinite loop or infinite recursion. Thus it reduces to halting.)
What is usually meant by this is that if you have a call
foo(a);
and somewhere else define
function foo(a:int) is
assert 0 < a && a < 128
...
end
then the compiler can check that a is, in fact, going to be in the open interval (0..128).
Some languages like D have reasonably powerful compile time constant folding and compile time condition checking (for D static assert(boolCond, msg);, IIRC C/C++ can use #if and pragma or #error)