欢迎所有爱好区块链技术的人加入。

ARCHIVES / 1202.HTML

合约内执行ERC20转账

Surou Ethereum-新手教程

假设有个合约ERC20充值方法,方法接收msg.sender发送的ERC20代币,并增加合约中的余额统计

import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
...
function rechargeMain(address mainChainErc20Addr, uint256 amount) payable external notContract returns (bool){
	...
	require(amount > 0, "The recharge amount is too small");
	require(IERC20(mainChainErc20Addr).balanceOf(msg.sender) >= amount, "Insufficient contract account balance");

	IERC20(mainChainErc20Addr).transfer(address(this), amount);
	...
	return true;
}

执行后提示

execution reverted: ERC20: transfer amount exceeds balance

经测试(Github Code)

function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
	_transfer(_msgSender(), recipient, amount);
	return true;
}

_msgSender()的地址为合约地址,测试交易(跳转地址)

所以我们需要使用transferFrom,代码修改为

import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
...
function rechargeMain(address mainChainErc20Addr, uint256 amount) payable external notContract returns (bool){
	...
	require(amount > 0, "The recharge amount is too small");
	require(IERC20(mainChainErc20Addr).balanceOf(msg.sender) >= amount, "Insufficient contract account balance");

	IERC20(mainChainErc20Addr).transferFrom(msg.sender, address(this), amount);
	...
	return true;
}

执行完,提示

execution reverted: ERC20: transfer amount exceeds allowance

查看代码(Github code)

function transferFrom(
address sender,
 address recipient,
 uint256 amount
) public virtual override returns (bool) {
	_transfer(sender, recipient, amount);

	uint256 currentAllowance = _allowances[sender][_msgSender()];
	require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
	unchecked {
		_approve(sender, _msgSender(), currentAllowance - amount);
	}

	return true;
}

需要先批准交易金额(津贴)(Github Code)

 function approve(address spender, uint256 amount) public virtual override returns (bool) {
	 _approve(_msgSender(), spender, amount);
	 return true;
 }

查看当前剩余允许值,(Github Code)

function allowance(address owner, address spender) public view virtual override returns (uint256) {
	return _allowances[owner][spender];
}

也可以执行increaseAllowance或decreaseAllowance增量增减调整

对于此次需求,执行rechargeMain前,需要先执行津贴充值

increaseAllowance(address spender, uint256 addedValue)

执行increaseAllowance的地址为当前充值转出地址
spender为当前转入合约地址
addedValue为当前充值金额
测试交易:https://ropsten.etherscan.io/tx/0x0f65cb2a7ca2bf0d6b1fdd65e943afb5c6305573dc3c3a960c2f86f71757c897