【问题标题】:I have multiple token holders for a smart contract but it is still considering the first one我有多个智能合约的代币持有者,但它仍在考虑第一个
【发布时间】:2018-03-08 06:35:03
【问题描述】:

考虑以下代码在 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
                };

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

【问题讨论】:

  • 您是否使用与from 地址对应的私钥进行签名?
  • 您好,谢谢您的回复。合约地址的私钥在哪里?我的意思是,当我单击创建按钮来创建合同时,它只会返回给我一个合同地址。我在这里使用的私钥是合约所有者的。这可能是一个错误,但我不知道合约地址也有私钥。
  • 合约没有私钥。您使用的私钥决定了谁在发送交易。如果您想从两个不同的帐户执行操作,您将使用两个不同的私钥进行签名。
  • 这就是我所说的我已经创建了一份合同。在创建时,我已经为合约提供了一些硬币。假设是 1000。此外,如果我的合约需要超过 1000 个,我已经给了所有者 2000 个硬币,我可以通过所有者帐户给它。现在在初始阶段,我想从合约地址发送交易。而且合约地址也没有私钥。比我如何从合约账户发送代币。
  • 你不能从合约账户发送代币。你所能做的就是调用合约中的函数。所以在合约中写一个发送代币的函数,然后调用它。

标签: blockchain ethereum solidity smartcontracts web3js


【解决方案1】:

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

首先需要注意的是,所有转账都可以通过调用合约来完成,而不是直接相互通信。现在到用例...

代币持有者 A -> 代币持有者 B: 在这种情况下,持有人 A 想要将一些代币转移给持有人 B。如果您使用持有人 A 的私钥签署交易,那么您可以简单地调用合约上的 transfer 函数contractAddress。这就是您通过在以下代码中发送交易所做的事情(如果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 -> 代币持有者 B 通过地址 C: 在这种情况下,地址 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 并没有将其标准化。 你可以在这里做的是设置合约的所有者,并在合约中使用onlyOwner 之类的修饰符作为mint 函数。这样的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 了解有关修饰符的更多信息。

【讨论】:

  • 你的答案是正确的,但它是片面的。我想要的正是在上面的 cmets 中。但无论如何感谢您的回答。它清除了概念,给了我更多的信心。
  • 我了解用于发送交易的私钥,并且私钥不适用于合约。但是,如果代币持有者是合约本身呢?让我们举这个例子。函数 ERC20(uint8 小数,uint256 totalSupply,字符串 tokenName,字符串 tokenSymbol)公共 { balanceOf[this] = totalSupply ** uint256(decimals);名称 = 令牌名称;符号 = 令牌符号; }
  • 让我澄清一下,您希望“合约将自己的代币转移到其他地址”,并且您正在寻找实现此目的的方法。对吗?
  • 是的,但不完全是。我并不是说将代币所有权转让给其他人或以这种方式转让代币。就像我想将 10000 个代币转移到一个地址一样。比目前它使用合同从所有者转移到该地址。我想从合同而不是所有者转移。我没有在构造函数中将硬币分配给 this(意味着合约)而不是 msg.sender(owner)。 ERC20 是一个构造函数
  • 如果您使用ERC20 函数作为构造函数,那么您实际上是在将“totalSupply”数量的硬币分配给合约。现在,如果我对您的理解正确,那么您希望能够将“合约币”转移到某个地址。如果是这样的话,你可以修改我之前提供的mint函数,将totalSupply = totalSupply.add(_amount);替换为balances[this] = balances[this].sub(_amount);即可达到效果。
猜你喜欢
  • 2021-12-17
  • 2022-08-15
  • 1970-01-01
  • 2022-11-12
  • 2017-08-03
  • 1970-01-01
  • 1970-01-01
  • 2021-09-17
  • 2021-11-28
相关资源
最近更新 更多