I'm trying to implement a function in Solidity that checks if the bit at a position is set or not, i.e. I want a function like:
function isBitSet(bytes24 b, uint pos) returns (bool){
return ...
}
I tried to transfer this approach to Solidity: Checking if a bit is set or not
function isBitSet(bytes24 b, uint pos) returns (bool){
return (b & (1 << pos)) != 0;
}
However, this does not work because (1 << pos) returns type uint256...
function isBitSet(bytes24 b, uint pos) internal view returns (bool){
return ( bytes32(b) & bytes32(1 << (pos+64)) ) != 0;
}
Related
I need to read each of the 256 bits stored in a bytes32 variable. I'm using Solidity 8.1
Thank you for any help you can offer
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Test {
// 1 byte is enough to hold about 1 typed character, 4 x "abcdefgh"
bytes32 public test = "abcdefghabcdefghabcdefghabcdefgh";
function accessByteByIndex(uint index) public view returns(bytes1) {
// since you need 32 bytes
require(index<32,"Index out of range");
return test[index];
}
function reverseBytes() public pure returns(bytes memory) {
uint num = 32;
bytes memory chars = new bytes(num);
bytes memory reverse = new bytes(num);
chars = "abcdefghabcdefghabcdefghabcdefgh";
uint i = 0;
for (i = 0; i < num; i++) {
reverse[i] = chars[num - 1 - i];
}
return reverse;
}
}
needed to cast the bytes32 variable to a uint256 then use the following function:
function isBitSet(uint256 b, uint256 pos) public pure returns (bool) {
return ((b >> pos) & 1) == 1;
}
I am trying to write a function to reverse the digits of a uint in a solidity smart contract.
I saw this answer here that shows how to reverse a string in solidity by looping through the bytes of a passed string from back to front, but since I am only concerned with integers I wondered if there was a way to do so that only used integers, and was able to appropriately handle overflows.
Thanks!
Searching around I found this answer that gives a solution to this very problem in C. I was able to tweak this to work in Solidity.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Reverse {
function reverse_recurse(uint i, uint r) internal returns(uint) {
if (i != 0) {
uint least_digit = i % 10;
if (r >= type(uint).max / 10 && (r > type(uint).max / 10 || least_digit > type(uint).max % 10)) {
return 0; /// Overflow
}
r = reverse_recurse(i / 10, r * 10 + least_digit);
}
return r;
}
// Reverses digits in a uint, overflow returns 0
function reverse_int(uint i) public returns(uint) {
return reverse_recurse(i, 0);
}
}
decoded input { "uint256 i": "12345" }
decoded output { "0": "uint256: 54321" }
Unlike the C solution this works only for unsigned ints as that was all I was needing.
Above answer seem to complicated to me so decided to create something on my own
function reverseNumber(uint n) public pure returns(uint) {
uint num = n;
uint reversedNum = 0;
while(true) {
if (reversedNum == 0) {
reversedNum = num % 10;
} else {
reversedNum = (reversedNum * 10) + (num % 10);
}
if(num < 10) {
break;
}
num = num / 10;
}
return reversedNum == n ? 1 : 0;
}
Apologies if this is stupid, but I made some simple code to get my point across. Namely it is this. If I use int x , y, from my main function as arguments, shouldn't I be able to use return() to export them back into the main function?
#include <stdio.h>
/*function prototype */
int add(int x, int y);
int
main()
{
int x, y;
printf("enter # to add ->\n");
scanf("%d", &x);
printf("enter # to add ->\n");
scanf("%d", &y);
/* function call */
/* print statement 1 */
printf("The sum is -> %d, x -> %d and y was-> %d \n", add(x, y));
/*print statement 2 always is fine*/
printf("The sum is -> %d", add(x,y));
/* print statement 3 */
printf(" the sum is -> %d, x-> %d, and y-> %d \n", add(x, y), x, y);
return(0);
}
/*function*/
int add(int x, int y)
{
int sum;
sum = x+y;
return(sum, x, y);
}
Sample
Print1 ex. If x,y input is 6,7 respectively I get "the sum is -> 13, x -> 6 and y was-> -1346575416". obviously there is something wrong with y..
Print3 ex. For this example is the easiest way to do it, but I need to know how to get out any manipulated values of x,y by-the function
I have tried renaming x,y vars in the function (i.e. xx=x, yy=y), adding them then using them in return(sum, xx, yy), but that did not help either.
Any help is appreciated
It is cannot be done in C, but you can try some methods, like using struct, or using pointer.
For example :
typedef struct _OP{
int x, y, sum;
}Operate;
Operate add(Operate addOperation){
addOperation.sum = addOperation.x + addOperation.y;
return addOperation;
}
int main(){
Operate num, result;
num.x = 10;
num.y = 5;
result = add(num);
printf("x : %i, y : %i, sum : %i", result.x, result.y, result.sum);
return 0;
}
Hope it helps,
I'm currently trying to offset bytes in solidity to implement a simple Caesar cipher decryption. However, I can't figure out how to do this. Here is my current code, which gives a few compiler errors in Remix:
function decrypt(bytes32 data, int key) public returns (bool) {
bytes32 decryptedData = data; // `data` here is the encrypted data
// decryption
for (int i = 0; i < decryptedData.length; i++) {
decryptedData[i] = (decryptedData[i] - key) % 256;
}
// returns if sha256(decryptedData) matches some value
}
However, this gives me the following errors:
TypeError: Expression has to be an lvalue.
decryptedData[i] = (decryptedData[i] - key) % 256;
^--------------^
TypeError: Operator - not compatible with types bytes1 and int256
decryptedData[i] = (decryptedData[i] - key) % 256;
^--------------------^
TypeError: Operator % not compatible with types bytes1 and int_const 256
decryptedData[i] = (decryptedData[i] - key) % 256;
^----------------------------^
Thanks!
Like Damian Green said, I'm a bit confused on the algorithm you're trying to write, but the contract below will decrypt a Caesar encrypted text. You should be able to modify it for your needs. (Please excuse the lazy hard-coding of ASCII values).
Note that you can't use bytes32 as that is treated as a special array in Solidity and is read-only. See "index access" section of http://solidity.readthedocs.io/en/develop/types.html#fixed-size-byte-arrays
pragma solidity ^0.4.17;
contract CaesarDecryption {
function decrypt(bytes data, int key) pure public returns (bytes) {
bytes memory decryptedData = data;
for (uint i = 0; i < decryptedData.length; i++) {
decryptedData[i] = decryptByte(decryptedData[i], key);
}
return decryptedData;
}
function decryptByte(byte b, int k) pure internal returns (byte) {
uint8 ascii = uint8(b);
uint8 asciiShift;
if (ascii >= 65 && ascii <= 90)
asciiShift = 65;
else if (ascii >= 97 && ascii <=122)
asciiShift = 97;
return byte(((ascii - asciiShift - k + 26) % 26) + asciiShift);
}
}
I have the following class functor in CUDA
class forSecondMax{
private:
int toExclude;
public:
__device__ void setToExclude(int val){
toExclude = val;
}
__device__ bool operator ()
(const DereferencedIteratorTuple& lhs, const DereferencedIteratorTuple& rhs)
{
using thrust::get;
//if you do <=, returns last occurence of largest element. < returns first
if (get<0>(lhs)== get<2>(lhs) /*&& get<0>(rhs) == get<2>(rhs)*/ && get<0>(lhs) != toExclude/* && get<0>(rhs)!= toExclude */) return get<1>(lhs) < get<1>(rhs); else
return true ;
}
};
is there a way to set the value of toExclude from the host?
All you need to do to solve achieve this is to define a constructor for the functor which sets the data member from an argument. So your class would look something like this:
class forSecondMax{
private:
int toExclude;
public:
__device__ __host__ forSecondMax(int x) : toExclude(x) {};
__device__ __host__ bool operator ()
(const DereferencedIteratorTuple& lhs,
const DereferencedIteratorTuple& rhs)
{
using thrust::get;
if (get<0>(lhs)== get<2>(lhs) && get<0>(lhs) != toExclude)
return get<1>(lhs) < get<1>(rhs);
else
return true ;
}
};
[disclaimer: written in browser, never tested or compiled, use at own risk]
To set the value prior to passing the functor to a thrust algorithm, create and instance of the functor and pass it to the thrust call, for example:
forSecondMax op(10);
thrust::remove_if(A.begin(), A.end(), op);
which would set the data member toExclude to a value of 10 in a new instance of the class, and use the instance in the stream compaction call.