我有多个智能合约代币持有者,但它仍在考虑第一个

I have multiple token holders for a smart contract but it is still considering the first one

考虑以下用于 ropsten 测试网中 web3js 和以太坊智能合约之间通信的代码。

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);
                        }
                    });    
                }); 

我有多个代币持有者,其中一个是具有代币初始值的合约地址,另一个是具有总供应量的代币所有者。我想从合同地址而不是合同所有者帐户中提供代币。如果我们像下面这样更改,则从所有者帐户进行的令牌转移工作正常

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
                };

但是上面的代码没有按预期工作。它确实为我提供了交易哈希,但其中没有分发代币。

让我们假设 ERC20 代币合约并检查不同的用例。

首先需要注意的是,所有的转账都只能通过调用合约来完成,而不是直接与对方通信。现在到用例...

代币持有人 A -> 代币持有人 B : 在这种情况下,持有人 A 想要将一些代币转移给持有人 B。如果您使用持有人 A 的私钥签署交易,那么您只需调用 contractAddress 合约上的 transfer 函数即可。这就是您通过在下面的代码中发送交易所做的事情(如果 myAddresscontractAddress 的合同中有高于 noOfTokens 的代币余额,这将起作用)

            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
            };

代币持有人 A -> 通过地址 C 的代币持有人 B : 在这种情况下,地址 C 想要代表持有人 A 进行交易。因此,要调用的标准函数是 transferFrom。假设持有人 A 已经对地址 C 进行了某种批准,并且 myAddress 指的是地址 C,您可以使用以下交易

            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
            };

就 ERC20 而言。有关更多信息,请参阅 https://theethereum.wiki/w/index.php/ERC20_Token_Standard。 你所做的感觉就像铸币,而 ERC20 并未将其标准化。 您在这里可以做的是设置合约的所有者,并为合约中的 mint 函数使用 onlyOwner 之类的修饰符。这样的 mint 函数看起来像

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;
}

通过这种方式,您可以从 myAddress 调用 mint 函数(如果该地址是所有者)并传递应该接收令牌的 userAddress。您还可以选择保留上限并通过在 mint 函数中引入检查或向其添加额外的修饰符(如 canMint)来限制令牌。您可以查看 https://solidity.readthedocs.io/en/develop/contracts.html#function-modifiers 以获取有关修饰符的更多信息。