由于当前项目需要对接到数字货币(基于ERC20),开发人员觉得我们自己维护nonce值太麻烦了,而且每次通过web3j去进行代币转账效率很低,所以想让我写一个智能合约去进行转账。找我写的原因是因为我在以前的项目做过,且开发过一个去中心化交易的智能合约。因为以前的项目也做了一年多了,有很多细节记不太清楚了,在网上找了一下,关于如何通过智能合约转账代币。具体代码实现如下:
pragma solidity ^ 0.4.21;
contract Token{
uint256 public totalSupply;
function transfer(address _to, uint256 _value) public returns(bool);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
function approve(address _spender, uint256 _value) public;
}
contract A {
Token TestToken;
function A(address contractAddress){
TestToken = Token(contractAddress);
}//初始化该合约
uint256 public a; //创建的合约代币总数
function aTransfer(address _to, uint256 _value) public returns(bool) {
TestToken.transfer(_to, _value); //查询该代币总量赋值给a
}
}
将下列的代码在remix上面进行部署,然后进行转账,再在代币中进行查询余额。你会发现余额一直是0,这就说明合约转账是没有成功的。
折腾了一个上午,后面回想到以前在做去中心化交易的过程中想到,一定要进行approve授权,所以在合约a进行转账之前我们要对a进行授权操作。
授权完成后,再进行转账操作,转账还是失败了。思来想去,后面想到了可能调用的msg.sender有关。于是找了一下以前的笔记:
关于msg.sender在多个合约相互调用时,如果用户user1 调用智能合约A,如果A中有msg.sender 时,msg.sender代表的是user1的地址,然后合约A调用合约B,如果合约B中有msg.sender,此时msg.sender代表的 是合约A的合约地址,而不是user1的账号地址。所以在我们的合约a中调用Token的transfer转账时,实际上相当于是从合约地址a转账到对应的账号地址,肯定不会成功,因为合约地址a 上是没有代币余额的。所以我们应该使用transferForm进行转账,修改代码之后重新部署并进行approve授权并进行转账。再查询余额,会发现转账成功。如下图所示:
现在合约转账成功之后,我们之需要改成批量转账就行了。具体的代码如下:
pragma solidity ^ 0.4.21;
contract Token{
uint256 public totalSupply;
function transfer(address _to, uint256 _value) public returns(bool);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
function approve(address _spender, uint256 _value) public;
}
contract A {
Token TestToken;
function A(address contractAddress){
TestToken = Token(contractAddress);
}
//初始化该合约
uint256 public a; //创建的合约代币总数
function aTransfer( address[] _to, uint256[] _value) public returns(bool) {
for(uint i=0; i <= _to.length ; i++){
TestToken.transferFrom(msg.sender, _to[i], _value[i]);
}
}
}