Does We3.toWei function accept decimal number? - ethereum

I am doing some research about Web3js.
I try to build one contract that can let anyone to purchase my token by ether.
I use testrpc to build my pricate chain
Here is my transfer function
handleTransfer: function(event) {
event.preventDefault();
var amount = parseInt($('#TTTransferAmount').val()); // get the ether amout
console.log('Pay ' + amount + ' ether');
var GustavoCoinCrowdsaleInstance;
web3.eth.getAccounts(function(error, accounts) {
if (error) {
console.log(error);
}
var account = accounts[0];
App.contracts.GustavoCoinCrowdsale.deployed().then(function(instance) {
GustavoCoinCrowdsaleInstance = instance;
console.log(typeof amount );
console.log( web3.toWei(amount, "ether"));
return GustavoCoinCrowdsaleInstance.sendTransaction({ from: account, value: web3.toWei(amount, "ether")})
}).then(function(result) {
alert('Pay Successful!');
$('#TTTransferAmount').val(0);
return App.getBalances();
}).catch(function(err) {
console.log(err.message);
});
});
}
I try to use web3.toWei function to converts an ethereum unit into wei
when I type console.log(web3.toWei(1,'ether'));
The result is fine,it will return 1000000000000000000
but when I type console.log(web3.toWei(0.1,'ether'));
it will return 0
Does toWei function only accept integer?
What should I need to do if I want to use 0.1 ether to purchase token?

Related

Not able to bridge deployed ERC20 token through POS Bridge using Maticjs, getting this error "execution reverted: ERC20: approve to the zero address"

Here is my code, I have also added the options as well in the approve function which contains the from, to, gasLimit but that also doesn't work for me
const { POSClient, use } = require('#maticnetwork/maticjs');
const { Web3ClientPlugin } = require('#maticnetwork/maticjs-web3');
const HDWalletProvider = require('#truffle/hdwallet-provider');
require('dotenv').config();
use(Web3ClientPlugin);
async function getPOSClient() {
const posClient = new POSClient();
return await posClient.init({
network: 'testnet',
version: 'mumbai',
parent: {
provider: new HDWalletProvider(
process.env.PVT_KEY,
process.env.GOERLI_RPC
),
defaultConfig: {
from: process.env.FROM_ADDRESS,
},
},
child: {
provider: new HDWalletProvider(
process.env.PVT_KEY,
process.env.MUMBAI_RPC
),
defaultConfig: {
from: process.env.FROM_ADDRESS,
},
},
});
}
async function approveToken() {
const posClient = await getPOSClient();
// console.log('🚀 ~ file: index.js:36 ~ approveToken ~ posClient', posClient);
const erc20Token = posClient.erc20(process.env.ROOT_TOKEN, true);
const result = await erc20Token.approve('1000');
const txHash = await result.getTransactionHash();
console.log('txHash', txHash);
const receipt = await result.getReceipt();
console.log('receipt', receipt);
}
approveToken();
The error which I'm getting while approving the token,
Error: execution reverted: ERC20: approve to the zero address
0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002245524332303a20617070726f766520746f20746865207a65726f2061646472657373000000000000000000000000000000000000000000000000000000000000
I have also mapped the token from polygon token mapper portal also. Please give your feedback
This error occurs when you are trying to approve an ERC20 token to the zero address.
Assuming the approve interface is approve(spender, amount)
I believe that if you add the approved address to this call const result = await erc20Token.approve(ADDRESS,'1000'); this issue will be resolved.

Send signed transactions to Ropsten or Truffle develop network with Trezor (Hardware Wallet)

Im trying to integrate web3js with Trezor in a truffle dev network or using ropsten test network.
The idea is to sign the transactions using the hardware wallet and then send a raw transaction using web3js
Im getting that we dont have balance to make the transaction, probably because web3js isnt taking one of the 10 truffle accounts and is using the trezor address that isnt in my local network..
On ropsten i have some ethers and i get "invalid address"
Is there a way to send a signed transactions (with trezor) using web3js into a truffle develop network? i mean, is there a way to include the trezor address into the truffle network?
The situation in truffle is explained more in details here, but the question could be generalized to "is there a way to include hardware wallets into truffle development network?" : https://github.com/trufflesuite/truffle/issues/973
Using ropsten I have managed to send a transaction and receive a transaction hash in the callback, but if we query for that transaction we get that the transaction doesnt exists.. so.. how is that possible?
I tried deploying a contract into Ropsten too and now im getting "Invalid address" when invoking a smart contract function. Maybe the signing function is wrong? anyone could integrate Trezor transaction signining with web3js?
Do you guys see anything wrong in the signing and sending process that we have followed? Maybe is there something wrong on the R, V and S parameters handling
..
Another important thing is that i am using https://github.com/ethereumjs/ethereumjs-tx for creating the raw transactions
Issues published in web3js, truffle and trezzor connect with more information:
https://github.com/trufflesuite/truffle/issues/973
https://github.com/ethereum/web3.js/issues/1669
https://github.com/trezor/connect/issues/130
kind regards
trezorLogin = async()=> {
let trezor= await this.getTrezor();
// site icon, optional. at least 48x48px
let hosticon = 'https://doc.satoshilabs.com/trezor-apps/_images/copay_logo.png';
// server-side generated and randomized challenges
let challenge_hidden = '';
let challenge_visual = '';
//use anonimous functions on callback otherwise returns cross origin errors
trezor.requestLogin(hosticon, challenge_hidden, challenge_visual, function (result){
if (result.success) {
console.log('Public key:', result.public_key); // pubkey in hex
console.log('Signature:', result.signature); // signature in hex
console.log('Version 2:', result.version === 2); // version field
console.log(result);
}else {
console.error('Error:', result.error);
}
});}
trezorSignTx= async(transaction)=> {
let trezor= await this.getTrezor();
// spend one change output
let address_n = "m/44'/60'/0'/0/0"
// let address_n = [44 | 0x80000000,
// 60 | 0x80000000,
// 0 | 0x80000000 ,
// 0 ]; // same, in raw form
let nonce = transaction.nonce.substring(2); // note - it is hex, not number!!!
let gas_price = transaction.gasPrice.substring(2);
let gas_limit = transaction.gasLimit.substring(2);
let to = transaction.to.substring(2);
// let value = '01'; // in hexadecimal, in wei - this is 1 wei
let value = transaction.value.substring(2); // in hexadecimal, in wei - this is about 18 ETC
let data = transaction.data.substring(2); // some contract data
// let data = null // for no data
let chain_id = 5777; // 1 for ETH, 61 for ETC
return new Promise (function (resolve,reject) {
trezor.ethereumSignTx(
address_n,
nonce,
gas_price,
gas_limit,
to,
value,
data,
chain_id,
function (response) {
if (response.success) {
console.log('Signature V (recovery parameter):', response.v); // number
console.log('Signature R component:', response.r); // bytes
console.log('Signature S component:', response.s); // bytes
resolve(response);
} else {
console.error('Error:', response.error); // error message
resolve(null);
}
});
})
}
getTrezorAddress = async() => {
let trezor= await this.getTrezor();
// spend one change output
let address_n = "m/44'/60'/0'/0/0";
trezor.ethereumGetAddress(address_n, function (result) {
if (result.success) { // success
console.log('Address: ', result.address);
} else {
console.error('Error:', result.error); // error message
}
});
}
getTrezor = async() => {
let trezorC;
await getTrezorConnect
.then(trezorConnect => {
trezorC= trezorConnect;
})
.catch((error) => {
console.log(error)
})
return trezorC;
}
sendTransaction= async(address, amount, id)=>{
let tokenInstance = this.props.smartContractInstance;
let getData = tokenInstance.mint.getData(address, amount);
let tx = {
nonce: '0x00',
gasPrice: '0x09184e72a000',
gasLimit: '0x2710',
to: CONTRACT_ADDRESS,
value: '0x00',
from:CONTRACT_OWNER_ADDRESS,
data: getData
};
let response = await this.trezorSignTx(tx);
let web3;
let _this = this;
if (response!=null){
getWeb3
.then(results => {
web3= results.web3;
let v = response.v.toString();
if (v.length % 2 != 0){
v="0"+v;
}
tx.r=Buffer.from(response.r,'hex');
tx.v=Buffer.from(v,'hex');
tx.s=Buffer.from(response.s,'hex');
let ethtx = new ethereumjs(tx);
console.dir(ethtx.getSenderAddress().toString('hex'), );
const serializedTx = ethtx.serialize();
const rawTx = '0x' + serializedTx.toString('hex');
console.log(rawTx);
//finally pass this data parameter to send Transaction
web3.eth.sendRawTransaction(rawTx, function (error, result) {
if(!error){
_this.props.addTokens(id)
.then(()=>{
_this.setState({modalOpen: true});
_this.props.getAllTransactions();
}
);
}else{
alert(error)
}
});
})
.catch((error) => {
console.log(error)
})
}else{
alert("There was an error signing with trezor hardware wallet")
}
}
The getTrezorConnect function is just get window.trezorConnect asynchronously because the object is injected as script
<script src="https://connect.trezor.io/4/connect.js"></script>
let getTrezorConnect = new Promise(function(resolve, reject) {
// Wait for loading completion
window.addEventListener('load', function() {
let trezorConnect = window.TrezorConnect
return resolve(trezorConnect)
})});
export default getTrezorConnect
Well, after a lot of trying we have managed to send a raw transaction signed with Trezor to Ropsten, Truffle (see the edit on the bottom of the answer) and also to a local private Geth network, so, the code is ok and there is no problem with Trezor integration on those environments
https://ropsten.etherscan.io/address/0x89e2c46b22881f747797cf67310aad1a831d50b7
This are the things that i had changed in order to make it possible to send signed transactions to the Ropsten testnet.
This assumes that you have your contract deployed into Ropsten and you have the contract address.
1) Get the address of your Trezor account
getTrezorAddress = async() => {
let trezor= await this.getTrezor();
// spend one change output
let address_n = "m/44'/1'/0'/0/0";
trezor.ethereumGetAddress(address_n, function (result) {
if (result.success) { // success
console.log('Address: ', result.address);
} else {
console.error('Error:', result.error); // error message
}
});
}
2) Put the trezor address into the from field of your raw transaction, get the nonce of the transaction by getting the transaction count for that address. Important: use the "pending" optional parameter on getTransactionCount to get all the transactions of the account, otherwise you will be overriting pending transactions.
getNonce = async(address) => {
let web3 = await this.getWeb3();
return new Promise (function (resolve,reject) {
web3.eth.getTransactionCount(address, "pending", function (error,result){
console.log("Nonce "+result);
resolve(result);
});
});
}
let count = null;
await this.getNonce("0xedff546ac229317df81ef9e6cb3b67c0e6425fa7").then(result => {
if(result.length % 2 !==0){
result = "0"+result;
}
count = "0x"+result;
});
let tx = {
nonce: count ,
gasPrice: web3.toHex(gasPriceGwei*1e9),
gasLimit: web3.toHex(gasLimit),
to: CONTRACT_ADDRESS,
value: '0x00',
data: getData,
chainId:chainId,
from:"yourTrezzorAddress"
};
3) The r, s, v parameters were incorrect, the right way to handle them is take that values for the trezor response and just convert it to hexa:
// response is the Trezor sign response
tx.v= response.v;
tx.r="0x"+response.r;
tx.s="0x"+response.s;
let ethtx = new ethereumjs(tx);.
const serializedTx = ethtx.serialize();
const rawTx = '0x' + serializedTx.toString('hex');
//finally pass this data parameter to send Transaction
web3.eth.sendRawTransaction(rawTx, someCallbackFunction);
Important: the mining time in ropsten will be between 15 and 30 secs so if in your someCallbackFunction you check for the transaction receipt, using the hash, you will get null as result, because the transaction is in a pending state.
4) To test it at ropsten we use Infura, so we change the web3 provider:
import Web3 from 'web3'
import HDWalletProvider from "truffle-hdwallet-provider";
let getWeb3 = new Promise(function(resolve, reject) {
// Wait for loading completion to avoid race conditions with web3 injection timing.
window.addEventListener('load', function() {
let results
let web3 = window.web3
// Checking if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined') {
// Use Mist/MetaMask's provider.
web3 = new Web3(web3.currentProvider)
results = {
web3: web3
}
console.log('Injected web3 detected.');
return resolve(results)
} else {
// Fallback to localhost if no web3 injection. We've configured this to
// use the development console's port by default.
// let provider = new Web3.providers.HttpProvider("https://ropsten.infura.io/your_infura_api_key")
let mnemonic = "infura mnemonic"
let provider = new HDWalletProvider(mnemonic, "https://ropsten.infura.io/your_infura_api_key")
web3 = new Web3(provider)
results = {
web3: web3
}
console.log('No web3 instance injected, using Local web3.');
return resolve(results)
}
})
})
export default getWeb3
EDIT:
This also works on Truffle! check the last comments of this issue https://github.com/trufflesuite/truffle/issues/973
We developed a small library to use Truffle with Trezor hardware wallets: https://github.com/rarible/trezor-provider
It can be used like this:
const { createProvider } = require('#rarible/trezor-provider')
module.exports = {
networks: {
ropsten: {
provider: function() {
//websocket and http urls are supported
return createProvider({ url: "{infura or other}", path: "m/44'/60'/0'/0/0", chainId: 3 })
},
network_id: 3
}
}
};

Redux saga: yield put not working inside nested callback

const { payload: {loginType, email, password, notification, self} } = action;
console.log("--TRY--");
Firebase.login(loginType, { email, password })
.catch(function(result) {
const message =
result && result.message ? result.message : 'Sorry Some error occurs';
notification('error', message);
self.setState({
confirmLoading: false
});
isError = true;
})
.then(function(result) {
if (isError) {
return;
}
if (!result || result.message) {
const message =
result && result.message
? result.message
: 'Sorry Some error occurs';
notification('error', message);
self.setState({
confirmLoading: false
});
} else {
self.setState({
visible: false,
confirmLoading: false
});
console.log("--RIGHT BEFORE I CHECK AUTH STATE--");
//the following does NOT fire
firebaseAuth().onAuthStateChanged(function*(user) {
console.log("THE GENERATOR RUNS");
if (user) {
console.log(user);
yield put({
type: actions.LOGIN_SUCCESS,
token: 'secret token',
profile: 'Profile'
});
yield put(push('/dashboard'));
}
else {
yield put({ type: actions.LOGIN_ERROR });
}
});
}
}); });
Hi. I'm currently working with redux saga for the first time. I've been trying to get yield put to fire in the callback of the firebaseAuth().onAuthStateChanged listener. The yield keyword won't work in a function that is not an ES6 generator, so I added an asterisk to the callback but now it won't execute at all. Would really appreciate any advice on the matter.
As you noticed, redux-saga effects can only be used within a generator function, and you cannot use a generator function as a regular function: calling a generator function only returns a special object.
The right way to approach this is to use an eventChannel: it lets you connect your saga to a source of events external to the redux ecosystem.
First create your eventChannel using the provided factory function: it hands you an emit function that you can use to emit events; then consume these events using the take effect.
import { eventChannel } from 'redux-saga';
import { cancelled, take } from 'redux-saga/effects';
// first create your eventChannel
const authEventsChannel = eventChannel( emit => {
const unsubscribe = firebaseAuth().onAuthStateChanged( user => {
emit({ user });
});
// return a function that can be used to unregister listeners when the saga is cancelled
return unsubscribe;
});
// then monitor those events in your saga
try {
while (true) {
const { user } = yield take (authEventsChannel);
// handle auth state
}
} finally {
// unregister listener if the saga was cancelled
if (yield cancelled()) authEventsChannel.close();
}

web3 balanceOf always 0

I'm trying to get the balance of an address on my smart contract using web3, but the balance is always 0. Using metamask on Rinkeby since my contract is deployed on rinkeby. https://rinkeby.etherscan.io/address/0x8e3a88be716ce7c8119c36558ec97bc634592255
You can verify the wallet has a balance by putting it in the balanceOf function on etherScan. Use the address 0x8b54A82a12bD5A7bA33B4842cA677E55f78a8612
let provider = web3.currentProvider;
web3 = new Web3(provider);
let abi = 'too long of a string to post here';
let MyContract = web3.eth.contract(JSON.parse(abi));
let myContractInstance = MyContract.at('0x8e3a88be716ce7c8119c36558ec97bc634592255');
let address = '0x8b54A82a12bD5A7bA33B4842cA677E55f78a8612';
function balanceOf(address) {
if (!address) {
return;
}
this.myContractInstance.balanceOf.call(address, function(error, balance) {
if (error) {
return;
}
alert(balance.c[0] + ' RHC');
});
}
balanceOf(address);
Here is the getBalance function on my contract
function balanceOf(address _owner) public view returns (uint256 balance) {
return balances[_owner];
}
Website implemented on http://robinhoodcoin.net/metamask.html
Code https://github.com/robinhoodcoin/robinhoodcoin.github.io/blob/master/metamask.html
EDIT
when I change the provider to be the following:
var web3 = new Web3(new Web3.providers.HttpProvider('https://rinkeby.infura.io/'));
I am able to get the balance. SO there is something up with using metamask as the provider.
The line at https://github.com/robinhoodcoin/robinhoodcoin.github.io/blob/master/metamask.html#L118 has a typo. It reads:
self.myContractInstance = self.MyContract.at(self.address);
but the address is stored at self.contractAddress, so it should read:
self.myContractInstance = self.MyContract.at(self.contractAddress);
After making that fix, the page works fine for me with MetaMask.

oracles implementation with smart contracts

I am trying to deploy a smart contract to a private Blockchain which uses oraclizeAPI.sol library code.
Basically the smart contract is a small implementation of oraclize.
The import does not work, either with the github link or with local import, solc compilation fails because of import.
Both of the below does not work, the contract is not getting properly compiled by solc
1.import "oraclizeAPI.sol";
2.import "github.com/oraclize/ethereum-api/oraclizeAPI.sol";
So, next approch i took was to copy the code of oraclizeAPI.sol, directly into the contract code file.
Now the contract gets compiled properly but the i am falling shot on gas every time, while deploying.
Error:
The contract couldn't be stored, please check your gas amount.
Now here are the details of the Blockchain.
genesis.json
{
"nonce": "0x0000000000000042",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"difficulty": "0x4000",
"alloc": {
"84840c340067c75806273d2524dfbae646a7c68f":
{ "balance": "1606938044258990275541962092341162602522202993782792835301376" }
},
"config": {
"chainId": 15,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"coinbase": "0x84840c340067c75806273d2524dfbae646a7c68f",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x8000000000000000"
}
I am currently trying to deply the contract using the coinbase id.
web3.eth.getBlock("latest").gasLimit
132661998547049420
web3.eth.getBalance('0x84840c340067c75806273d2524dfbae646a7c68f').e
60
contract code:
contract oraclizeExample is usingOraclize {
string public data;
event newOraclizeQuery(string description);
event newData(string data);
event eventC(string data);
function oraclizeExample() payable {
update();
}
function __callback(bytes32 myid, string result) {
if (msg.sender != oraclize_cbAddress()) throw;
data = result;
newData(result);
//return result;
}
function eventCheck(string dataFClient) returns (string) {
eventC(dataFClient);
return dataFClient;
}
function update() payable returns (string) {
newOraclizeQuery("Oraclize query was sent, standing by for the answer..");
oraclize_query("URL", "json(https://jewel-api.herokuapp.com/jewel/58d89d264d59a000110829bb).invoice_num");
return "update function was called!";
}
}
The code of contract creation.
var ContractABI = web3.eth.contract(JSON.parse(interface));
var SaveContract = ContractABI.new(
{
from: account,
data: bytecode,
gas: '93048696279858031'
}, function (e, contract) {
if(e){
console.log(e, contract);
return;
}
if (typeof contract.address !== 'undefined') {
console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
fs.writeFileSync('./contracts_data/'+ contract_name + '_final', 'Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash)
return;
}
});
If you want to check the complete contract code with the and the way i am doing this please got to this link.
https://github.com/utkarsh17ife/oraclizeExample/tree/master/contracts_data
Or the complete implementation with node as well:
https://github.com/utkarsh17ife/oraclizeExample
And yes i am able to mine other contract using this setup.
Comment if you need further info on this.
If you are using a private chain you must run the ethereum-bridge, you are getting a throw because your smart contract invokes the oraclize_query function on deployment (constructor function) but no Oraclize contracts were found on your chain.