Why does calling `SSTORE` on a dynamic bytes value of length 32 always result in the value being equal to `0x000...080`? - solidity

Consider this snippet of Solidity (version ^0.8.9):
bytes32 key = bytes32(0);
bytes memory val = abi.encodePacked(bytes32(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF));
bytes32 result;
assembly {
sstore(key, val)
result := sload(key)
}
// Expected: result = 0xFFF...FFF
// Actual: result = 0x000...080
result;
result is always equal to 0x000...080 regardless of the value of val. This is surprising to
me; I'd expect result to be equal to val.
Note that if val is of type bytes32, then this issue disappears, and val equals result.

Related

Input out of range for Int datatype, not passing a testcase

I am trying to solve the following question on LeetCode; Write a function that takes an unsigned integer and returns the number of '1' bits it has. Constraints: The input must be a binary string of length 32.
I have written the following code for that which works fine for inputs 00000000000000000000000000001011 and 00000000000000000000000010000000 (provided internally by the website) but give output 0 for input 11111111111111111111111111111101 and in my local compiler for the last input it says "out of range"
class Solution {
// you need treat n as an unsigned value
fun hammingWeight(n:Int):Int {
var num = n
var setCountBit = 0
while (num > 0) {
setCountBit++
num= num and num-1
}
return setCountBit
}
}
To correctly convert binary string to Int and avoid "out of range error", you need to do the following (I believe LeetCode does the same under the hood):
fun binaryStringToInt(s: String): Int = s.toUInt(radix = 2).toInt()
"11111111111111111111111111111101" is equivalent to 4294967293. This is greater than Int.MAX_VALUE, so it will be represented as negative number after .toInt() convertion (-3 in this case).
Actually, this problem could be solved with one-liner in Kotlin 1.4:
fun hammingWeight(n: Int): Int = n.countOneBits()
But LeetCode uses Kotlin 1.3.10, so you need to adjust your solution to handle negative Ints as well.
Please change the type of your input variable from Int to a type like Double .At the moment The given value is bigger than the maximum value that a type Int number can store.

assignments are not expressions, and only expressions are allowed in this context --- how to resolve this error

I am trying to find the find the result of num1 raised to the power num2:
This is my code ->
fun power(num1 : Int, num2: Int): Int {
var result = 1
while (num2 != 0) {
return result *= num1
num2--
}
}
But the above code is producing the following error -->
Calculator.kt:30:16: error: assignments are not expressions, and only expressions are allowed in this context
return result *= num1
^
Calculator.kt:33:5: error: a 'return' expression required in a function with a block body ('{...}')
}
^
I have read a number of articles but not able to understand. Any help will be highly appreciated.
Thank you
An expression is something that evaluates to a value. An assignment is something that assigns a value to a variable or property.
x *= y is an assignment that is shorthand for x = x * y.
You cannot return an assignment, because it does not evaluate to a value. An assignment contains an expression on the right side of the equals sign, but as a whole does not represent an expression.
There are some other syntax problems you have. You can't modify a function paramter's value (num2-- isn't allowed).
The logic also doesn't make sense. return returns an expression immediately. To fix your code, you need to create a local variable from num2, and move the return statement to the end.
fun power(num1 : Int, num2: Int): Int {
var result = 1
var count = num2
while (count != 0) {
result *= num1
count--
}
return result
}
FYI, there's a function called repeat that is simpler than using a while loop with a counter. It runs the code inside the brackets by the number of times you give.
fun power(num1 : Int, num2: Int): Int {
var result = 1
repeat(num2) {
result *= num1
}
return result
}
You function contains multiple errors, I suggest you to study Kotlin, here a reference. Kotlin website has some more material.
Back to your problem, I have modified your function:
fun power(num1 : Int, num2: Int): Int {
var result = 1
var num2_local = num2
while (num2_local != 0) {
result *= num1
num2_local--
}
return result
}
Problems with your version:
you return from the function immediately
basic types args passed to kotlin functions are passed by const copy, this means that you cannot modify them (e.g num2--)
If you keep a local modifiable reference (var keyword) withing your function, then you achieve your goal

while loop and variable not changing

function test(num){
var root1 = Math.sqrt(num);
var ind=2;
while(ind<=root1){
if (ind%num==0 && IsPrime(ind)==true) {
num=ind;
}
ind++;
}
return num;
}
Hi, in this code the function must return the largest prime factor of a given number, but the function returns the same number
For example: test(123) returns 123
You have two problems:
You want to check if num can be divided by ind, not the other way round. The test for that would be: num % ind == 0.
You should not re-use the num variable for the result. That way you overwrite the original number and the result will be wrong. Declare a new variable, for instance, result.

Kotlin: Unexpected value for 2 Int multiplication

I've written a function to round a value in billion, here is my code:
private fun roundBillion(value: Double): Int {
val a = (value / 1000000).toInt()
val res = a * 1000000
return res
}
but when I execute the function I get an unexpected value in res variable. here is variables inspection when the break point is on return statement:
value = 1.7636265135946954E11
a = 176362
res = 268340864
I can't figure out where the problem is!
What you are experiencing is an integer overflow.
Double.MAX_VALUE is 1.7976931348623157E308.
Int.MAX_VALUE is 2147483647. Your number in the calculation (i.e. 176362000000) exceeds that.

How to use ByteArray.getOrElse

I don't undertand how to specify the default value for `ByteArray.getOrElse() function.
I tried:
myInt = dat.getOrElse(0, 0).toInt()
but compiler complains with the following error:
The integer literal does not conform to the expected type (Int) -> Byte
How to specify the default value?
The expected type of the second argument (defaultValue) is (Int) -> Byte which is a lambda that takes an Int and returns a Byte.
myInt = dat.getOrElse(index = 100, defaultValue = {
i ->
// use i to calcuate your Byte that should be returned...
// or return a fixed value
i * 1 // for example
})
Signature of getOrElse:
fun ByteArray.getOrElse(
index: Int,
defaultValue: (Int) -> Byte
): Byte
The second argument is a function literal
myInt = dat.getOrElse(100, { /** what is there is no element 100*/ 0 })