0
votes

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.

1
Are you signing with the private key that corresponds to the from address? - user94559
Hey Thanks for the reply. Where is the private key of contract address? I mean when I click on create button to create a contract it just return me with a contract address. Private key I have used here is of contract owner. That may be a mistake but I dont know that there is a private key for contract address too. - Harsh
Contracts don't have private keys. The private key you use determines who is sending the transaction. If you want to do things from two different accounts, you'll be signing with two different private keys. - user94559
Thats what I am telling I have created an contract. At creation time I have given some coins to the contract. lets say 1000. Also I have given 2000 coins to owner in case if my contract needs more than 1000, than I can give it through owner account. Now at initial stage I want to send transaction from contract address. And also contract address doesn't have private key. Than how will i send tokens from contract account. - Harsh
You can't send tokens from the contract's account. All you can do is call functions in the contract. So write a function in the contract that sends tokens, and then call it. - user94559

1 Answers

0
votes

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.