Considering the below code for communicating between web3js and ethereum smart contract in ropsten test net.
web3.eth.getTransactionCount(contractAddress).then(function(lastCountOfTransaction){
var rawTransaction = {
"from": contractAddress,
"nonce": "0x" + lastCountOfTransaction.toString(16),
"gasPrice": web3.utils.toHex(1 * 1e9), //1 can be changed to n gwei
"gasLimit": web3.utils.toHex(1000000), // 1000000 can be to set to any n number
"to": userAddress,
"value": "0x0",
"data": ContractObject.methods.transfer(userAddress, noOfTokens).encodeABI(),
"chainId": chainId
};
var tx = new Tx(rawTransaction);
tx.sign(privKey);
var serializedTx = tx.serialize();
web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'),function(err,hash){
if (!err){
console.log(hash);
resolve(hash);
}
else{
console.log(err);
resolve(err);
}
});
});
I have multiple token holders like one is contract address which has initial value of tokens and one is token owner which has total number of supply. I want to give tokens from contract address and not from contracts owner account. Token transfer from owner account is working if we change like below
web3.eth.getTransactionCount(myAddress).then(function(lastCountOfTransaction){
var rawTransaction = {
"from": myAddress,
"nonce": "0x" + lastCountOfTransaction.toString(16),
"gasPrice": web3.utils.toHex(1 * 1e9), //1 can be changed to n gwei
"gasLimit": web3.utils.toHex(1000000), // 1000000 can be to set to any n number
"to": contractAddress,
"value": "0x0",
"data": ContractObject.methods.transfer(userAddress, noOfTokens).encodeABI(),
"chainId": chainId
};
But the above code is not working as expected. It do provide me transaction hash but in that tokens are not distributed.
Lets assume ERC20 token contract and check out different use cases.
First thing you need to note is that all the transfers can be done by calling the contract only, not by communicating with each other directly. Now to the use cases...
Token Holder A -> Token Holder B :
In this scenario, Holder A wants to transfer some tokens to Holder B. If you sign a transaction using private key of holder A, then you can simply call the transfer
function on contract at contractAddress
. And this is what you are doing by sending transaction in below code (which will work if myAddress
has a balance of tokens above noOfTokens
in contract at contractAddress
)
var rawTransaction = {
"from": myAddress,
"nonce": "0x" + lastCountOfTransaction.toString(16),
"gasPrice": web3.utils.toHex(1 * 1e9), //1 can be changed to n gwei
"gasLimit": web3.utils.toHex(1000000), // 1000000 can be to set to any n number
"to": contractAddress,
"value": "0x0",
"data": ContractObject.methods.transfer(userAddress, noOfTokens).encodeABI(),
"chainId": chainId
};
Token Holder A -> Token Holder B via Address C :
In this scenario, Address C wants to do a transaction on behalf of Holder A. As such the standard function to call is transferFrom
. Assuming that some sort of approval has been given from Holder A to Address C, and that myAddress
refers to Address C, you can use the below transaction
var rawTransaction = {
"from": myAddress, // refers to Address C
"nonce": "0x" + lastCountOfTransaction.toString(16),
"gasPrice": web3.utils.toHex(1 * 1e9), //1 can be changed to n gwei
"gasLimit": web3.utils.toHex(1000000), // 1000000 can be to set to any n number
"to": contractAddress,
"value": "0x0",
"data": ContractObject.methods.transferFrom(userAddressA, userAddressB, noOfTokens).encodeABI(),
"chainId": chainId
};
This is as far as ERC20 goes. Refer https://theethereum.wiki/w/index.php/ERC20_Token_Standard for more info.
What you are doing feels like minting, and ERC20 doesn't standardize that.
What you can do here is that setup an owner of the contract and use a modifier like onlyOwner
for a mint
function in the contract. Such a mint
function can look something like
function mint(address _to, uint256 _amount) onlyOwner canMint returns (bool) {
totalSupply = totalSupply.add(_amount);
balances[_to] = balances[_to].add(_amount);
Mint(_to, _amount);
return true;
}
This way you can call the mint
function from myAddress
(if that address is the owner) and pass the userAddress
who should receive the tokens. You can also choose to keep an upper limit and make the tokens capped by introducing check in the mint
function or by adding an additional modifier (like canMint
) to it. You can check out https://solidity.readthedocs.io/en/develop/contracts.html#function-modifiers for more info on modifiers.