【问题标题】:Error calling deposit function on ERC20 escrow contract在 ERC20 托管合约上调用存款函数时出错
【发布时间】:2021-12-13 22:40:52
【问题描述】:

我写这个合约是为了托管给定类型的 ERC20 代币(代币的地址在调用构造函数时给出)。但是每次调用deposit函数往合约中存入一些代币时,我总是交易失败,我不知道为什么。


pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MainEscrow is Ownable {

    IERC20 public token;

    event Deposited(
        address indexed payee,
        address tokenAddress,
        uint256 amount
    );
    event Withdrawn(
        address indexed payee,
        address tokenAddress,
        uint256 amount
    );

    // payee address => token address => amount
    mapping(address => mapping(address => uint256)) public deposits;

    // payee address => token address => expiration time
    mapping(address => mapping(address => uint256)) public expirations;

    constructor(address _tokenAddress) {
        token = IERC20(_tokenAddress);
    }

    function deposit(
        address _payee,
        uint256 _amount,
        uint256 _expiration
    ) public {
        token.transferFrom(msg.sender, address(this), _amount);
        deposits[_payee][address(token)] += _amount;
        expirations[_payee][address(token)] = block.timestamp + _expiration;
        emit Deposited(_payee, address(token), _amount);
    }

    function withdraw(address payable _payee, uint256 _amount) public {
        uint256 totalPayment = deposits[_payee][address(token)];
        require(totalPayment >= _amount, "Not enough value");
        token.approve(_payee, _amount);
        require(token.transfer(_payee, _amount));
        deposits[_payee][address(token)] = totalPayment - _amount;
        emit Withdrawn(_payee, address(token), _amount);
    }

    function refund(address payable _payee) public {
        require(
            block.timestamp > expirations[_payee][address(token)],
            "The payment is still in escrow."
        );
        uint256 payment = deposits[_payee][address(token)];
        token.approve(msg.sender, payment);
        require(token.transfer(msg.sender, payment), "Transfer failed");
        deposits[_payee][address(token)] = 0;
        emit Withdrawn(msg.sender, address(token), payment);
    }
}

【问题讨论】:

    标签: ethereum solidity erc20


    【解决方案1】:

    deposit() 函数中几乎只有一行可能失败:

    token.transferFrom(msg.sender, address(this), _amount);
    

    (理论上它也可以因为以下两行的整数溢出而恢复,但这是非常不可能的。)

    这一行在token 合约上执行函数tranferFrom()。正如ERC-20 标准所定义的那样,如果令牌发送者没有足够的余额,或者如果他们没有批准调用者(在您的情况下为MainEscrow 地址)来花费他们的大量令牌,则该函数应该恢复。

    所以要么代币发送者没有足够的余额,要么他们没有从他们在代币合约上的地址调用approve(<MainEscrow_address>, <amount>)函数。

    【讨论】:

    • 谢谢我错过了批准功能。
    猜你喜欢
    • 1970-01-01
    • 2013-04-01
    • 2018-12-26
    • 2011-06-13
    • 1970-01-01
    • 2021-11-24
    • 2022-01-01
    • 2020-01-07
    • 2013-05-23
    相关资源
    最近更新 更多