How to properly pass uint256 numbers to smart contract from frontend? - ethereum

I have some math on frontend, which works good, but when math calculate big Numbers like this 1.1350120633522164e+23
I get error
Unhandled Rejection (Error): invalid number value
(arg="minDestinationAmount", coderType="uint256",
value="1.1350120633522164e+23", version=4.0.44)
I used BN
const minDestBN = new BigNumber(input)
const minDestinationAmount = minDestBN.multipliedBy(99).dividedBy(100)
res minDestinationAmoun = 1.1350120633522164e+23
How to convert such numbers 1.1350120633522164e+23 to uint256 on frontend side ?

This help me
BigNumber.config({ EXPONENTIAL_AT: 1e+9 })
let minDestinationAmount = minDestBN.multipliedBy(99).dividedBy(100)
minDestinationAmount = String(minDestinationAmount)
But would be great to hear best practice

Related

Error in javascript reduce method using typescript

I am learning Typescript by building a node application. I am using MySQL via sequelize for the database. I want to use .reduce() method in one of the results I got from the database.
Here is my code:
const orderedInstances = await createOrderedItemClass.findAll({where: {cartId:
cart.dataValues.id}});
orderedInstances.reduce((prev, current)=>{
return prev.dataValues.food_total_sum as number + current.dataValues.food_total_sum as
number
},)
Here is my error from typescript:
Argument of type '(prev: createOrderedItemClass, current: createOrderedItemClass) => number'
is not assignable to parameter of type '(previousValue: createOrderedItemClass, currentValue:
createOrderedItemClass, currentIndex: number, array: createOrderedItemClass[]) =>
createOrderedItemClass'.
Type 'number' is not assignable to type 'createOrderedItemClass'.
How do I fix this?
Reduce works differently. It is not prev and current value, but more like accumulator and current value.
So, the result of iteration is stored in the first argument which in your case is 'prev'. The result of iteration is a number. And you try to access dataValues.food_total_sum in a number which is an error.
Try like this:
const orderedInstances = await createOrderedItemClass.findAll({where: {cartId:
cart.dataValues.id}});
orderedInstances.reduce((prev, current)=>{
return prev + current.dataValues.food_total_sum as
number
}, 0)

yubihsm2 signatures are invalid when signing ETH transactions

I am trying to figure out how to get this yubihsm2 to work with signing eth transactions. I have been using the python lib and so far i have had some basic setup. Below is an abbreviation of what i have
web3_endpoint = ''
web3 = Web3(HTTPProvider(web3_endpoint))
hsm = YubiHsm.connect("http://localhost:12345")
session = hsm.create_session_derived(1, "password")
key = session.get_object(1,OBJECT.ASYMMETRIC_KEY)
#key = AsymmetricKey.generate(session, 1, "EC Key", 1, CAPABILITY.SIGN_ECDSA, ALGORITHM.EC_K256)
pub_key = key.get_public_key()
#raw_pub = pub_key.public_bytes(
# encoding=serialization.Encoding.DER,
# format=serialization.PublicFormat.SubjectPublicKeyInfo
# )
raw_pub = pub_key.public_bytes(
encoding=serialization.Encoding.X962,
format=serialization.PublicFormat.UncompressedPoint
)
print ("Public key (Uncompressed):\n",binascii.b2a_hex(raw_pub))
unindexPub = raw_pub[1:]
public_key_hash = Web3.keccak(unindexPub)
address_bytes = public_key_hash[-20:]
address = address_bytes.hex()
print(address)
Now so far i can consistently get the same public key and it looks correct. I then get the same public key each time. When i say correct, the formatting looks correct and is the correct number of bytes.
1). should i be using the commented out public key formatting or the uncompressed X962 encoding that i have above.
From there, this is where things get a bit weird
transaction = {
'to': Web3.toChecksumAddress('0x785AB1daE1b0Ee3f2412aCF55e4153A9517b07e1'),
'gas': 21000,
'gasPrice': Web3.toWei(5, 'gwei'),
'value': 1,
'nonce': 1,
'chainId': 4,
}
serializable_transaction = serializable_unsigned_transaction_from_dict(transaction)
transaction_hash = serializable_transaction.hash()
print(transaction_hash.hex())
# sign the transaction hash and calculate v value
signature = key.sign_ecdsa(transaction_hash,hashes.SHA3_256())
r, s = ecdsa.util.sigdecode_der(signature, ecdsa.SECP256k1.generator.order())
print("r: "+str(r)+"\ns: "+str(s))
v = 28
# encode the transaction along with the full signature and send it
encoded_transaction = encode_transaction(serializable_transaction, vrs=(v, r, s))
web3.eth.sendRawTransaction(encoded_transaction)
I am settings v to 28.. i also test it with 27.. I could use the correct amount with the chainid.. but it's not necessary right from the perspective of trying to get a valid signature (recoverable to get the same public key each time). Sometimes i am getting the error "invalid sender" and other times i am getting the error "insufficient gas." If i take the signature output and use a javascript lib to try to find the public key, each time i am getting a different public key. But i keep consistently generating the same public key from the yubihsm2 in this python app.
I have also commented out in sign_ecdsa the hashing function as i am passing in the data already hashed (in order to use keccak256).
Is there something i am missing? Why are these transactions not signing correctly for eth?
i am getting some of those serialization helpers from enter link description here
helper serialization functions
Thanks

How to work with data returned by mysql select query in nodejs

I am working on a discord bot written in nodejs, the bot utilises a mysql database server to store information. The problem I have run into is that I cannot seem to retrieve the data from the database in a neat way, every single thing I try seems to run into some issue or another.
The select query returns an object called RowDataPacket. When googling every single result will reference this solution: Object.values(JSON.parse(JSON.stringify(rows)))
It postulates that I should get the values back, but I dont I get an array back that is as hard to work with as the rowdatapacket object.
This is a snippet of my code:
const kenneledMemberRolesTableName = 'kenneled_member_roles'
const kenneledMemberKey = 'kenneled_member'
const kenneledMemberRoleKey = 'kenneled_member_role_id'
const kenneledStaffMemberKey = 'kenneled_staff_member'
const kenneledDateKey = 'kenneled_date'
const kenneledReturnableRoleKey = 'kenneled_role_can_be_returned'
async function findKenneledMemberRoles(kenneledMemberId) {
let sql = `SELECT CAST(${kenneledMemberRoleKey} AS Char) FROM ${kenneledMemberRolesTableName} WHERE ${kenneledMemberKey} = ${kenneledMemberId}`
let rows = await databaseAccessor.runQuery(sql)
let result = JSON.parse(JSON.stringify(rows)).map(row => {
return row.kenneled_member_role_id
})
return result
}
This seemed to work, until I had to do a type conversion on the value, now the dot notations requires me to reference row.CAST(kenneled_member_role_id AS Char), this cannot work, and I have found no other way to retrieve the data than through dot notation. I swear there must be a better way to work with mysql rowdatapackets but the solution eludes me
I figured out something that works, however I still feel like this is an inelegant solution, I would love to hear from others if I am misunderstanding how to work with mysql code in nodejs, or if this is just a consequence of the library:
let result = JSON.parse(JSON.stringify(rows)).map(row => {
return row[`CAST(${kenneledMemberRoleKey} AS CHAR)`];
})
So what I did is I access the value through brackets instead of dot notation, this seems to work, and at least makes me able to store part of or the whole expression in a constant variable, hiding the ugliness.

Solidity and Web3 sha3() methods return something else

In my contract, I have a function that returns the sha3 hash of a certain set of values. While running some tests I found that the value returned from this function differs from the hash value generated by web3.utils.sha3() (with identical arguments).
Here is the code:
Solidity
function hashInfo() public onlyOwner view returns (bytes32) {
bytes32 hash = sha3(
'0x969A70A4fa9F69D2D655E4B743abb9cA297E5328',
'0x496AAFA2960f3Ff530716B5334c9aFf4612e3c27',
'jdiojd',
'oidjoidj',
'idjodj',
12345
)
return hash;
}
JS (web3)
async function testHash(instance){
const contractHash = await instance.methods.hashInfo().call({from: '0x969A70A4fa9F69D2D655E4B743abb9cA297E5328'});
const localHash = web3.utils.sha3(
'0x969A70A4fa9F69D2D655E4B743abb9cA297E5328',
'0x496AAFA2960f3Ff530716B5334c9aFf4612e3c27',
'jdiojd',
'oidjoidj',
'idjodj',
12345
)
console.log(contractHash);
console.log(localHash);
console.log('local == contract: ' + (contractHash == localHash));
}
The resulting console output is:
0xe65757c5a99964b72d217493c192c073b9a580ec4b477f40a6c1f4bc537be076
0x3c23cebfe35b4da6f6592d38876bdb93f548085baf9000d538a1beb31558fc6d
local == contract: false
Any ideas? Does this have something to do with passing multiple arguments to the functions? I have also tried to convert everything to a string and concatenate them into one single string, but also without success.
Thanks in advance!
UPDATE
I found out there also if a web3 method called web3.utils.soliditySha3(). This too did not work and gave the following result:
0xe65757c5a99964b72d217493c192c073b9a580ec4b477f40a6c1f4bc537be076
0x0cf65f7c81dab0a5d414539b0e2f3807526fd9c15e197eaa6c7706d27aa7a0f8
local == contract: false
I'm happy I came after your update as I was just gonna suggest solditySHA3. Now that you've got the right function your problem is most likely with Soldity packing it's parameters.
As you can see here, sha3 is an alias to keccak256 which tightly packs it's arguments. Following the link on that page takes you here which fully explains how it's handled. Basically just take the inputs to soliditySHA3 and pack the bits as if they were the sizes of the variables you used. So if you hashed two uint32s (32 bits each, 64 total) you need to take the 2 64 bit Javascript numbers and compress them into 1 Javascript number.
For cases where more than 64 bits are needed I believe you can pass sequential ints (sets of 64 bits) to soliditySHA3 or you could use a BigInt. Personally, I usually try to only hash 256 bit variables together to avoid having to manually pack my bits on the JS end, but we all know that space constraints are huge in Solidity. I hope I helped, and let me know if you have further questions.

Function to convert a decimal into that of any base

I am doing this question via an Online learning platform, and there are test cases assigned which i must pass. The topic is Higher Order Functions.
Here is the question:
Write a function make_decimal_to_n_ary_converter that accepts a number n where 1 < n < 17, and returns a number converter that converts a given decimal number into that of base n.
Below is my code(I am supposed to use an inner function i.e converter(x))
def make_decimal_to_n_ary_converter(n):
def converter(x):
if x==0 or x==1:
return x
i=x
b=('A','B','C','D','E','F')
result = ""
while i>0:
a=i%n #3
if a<10:
result = str(i%n)+result
else:
d=a-10
result = b[d] + result
i=i//n
return result
return converter
#Lines below are not to be changed, part of qn
decimal_to_binary = make_decimal_to_n_ary_converter(2)
decimal_to_octal = make_decimal_to_n_ary_converter(8)
decimal_to_hexadecimal = make_decimal_to_n_ary_converter(16)
Here are some test cases that my code passes:
decimal_to_binary(213)
11010101
decimal_to_octal(213)
325
decimal_to_hexadecimal(213)
D5
make_decimal_to_n_ary_converter(15)(213)
E3
However, my code fails some private test cases, and feedback that i received was that my logic in the while loop is wrong. However, after printing some numbers, i failed to see anything wrong.
Would appreciate any help, thank you!
Solved it. My mistake was that for base cases x , i had to return a string instead.