0

I'm trying to do Escrow.sol with ERC20 token. When I deploy the Escrow.sol on Remix and wanna deposit 10 tokens, it appears The called function should be payable if you send value and the value you send should be less than your current balance. So did the function of withdraw.

How can I fix it?

the following is my erc20.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol";

contract MyToken is ERC20 {
    constructor() ERC20("GINWEI", "GW") public payable {
        _mint(msg.sender, 1000);
    }
}

and the following is escrow.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

import "./erc20.sol";

contract MyEscrow {

    mapping(address => mapping(address => uint256)) public _deposits;
    address payable payee = payable(msg.sender);
    MyToken token;

    function deposit(uint256 amount) public payable {
        token.approve(address(this), amount);
        token.transfer(address(this), amount);
        _deposits[payee][address(token)] += amount;
    }

    function depositsOf() public view returns (uint256) {
        return _deposits[payee][address(token)];
    }

    function withdraw(uint256 payment) public payable {
        _deposits[payee][address(token)] -= payment;
        payee.transfer(payment);
    }
}
1
  • Can you show how are you calling the functions from your test?
    – Julissa DC
    Jun 20 at 13:19

2 Answers 2

1

Your MyEscrow smart contract have any issues, let me explain them:

  • When you declare this statement MyToken token; like storage variable, you must instantiate it with the erc20's smart contact address for use ERC20 methods. An example how to fix this issue:

    MyToken token = MyToken([addressERC20SmartContract]);

  • token.approve(address(this), amount); this statement is wrong because you're approving your MyEscrow smart contract to transfer an token quantity that it doesn't have. To solve it, a user must call approve() from your ERC20 smart contract in this case MyToken smart contract. When call approve, he must pass these values inside these paramters:

    • spender: MyEscrow smart contract address;
    • amount: how many token MyEscrow can transfer from your wallet.
  • Finally, in withdraw function for transfer an ERC20 from smart contract to user wallet you can use transfer() ERC20 method and pass inside it the msg.sender and the value to withdraw.

I have corrected your MyEscrow smart contract in this way:

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

import "./erc20.sol";

contract MyEscrow {

    mapping(address => mapping(address => uint256)) public _deposits;
    address payable payee = payable(msg.sender);
    MyToken token;

    constructor(address _myToken) {
        token = MyToken(_myToken); 
    }

    function deposit(uint256 amount) public payable {
        token.transferFrom(msg.sender, address(this), amount);
        _deposits[payee][address(token)] += amount;
    }

    function depositsOf() public view returns (uint256) {
        return _deposits[payee][address(token)];
    }

    function withdraw(uint256 payment) public payable {
        _deposits[payee][address(token)] -= payment;
        token.transfer(msg.sender, payment);
    }
}
1
  • thx for ur explaination! But when i tried to deposit by the modified escrow.sol, it appears Reason provided by the contract: "ERC20: insufficient allowance"
    – ginwei
    Jun 20 at 15:02
0

After several trying, I combined the sol from @Kerry99 and my original code, and it works perfectly!

the func approve() has been overriden.

contract MyEscrow {

    mapping(address => mapping(address => uint256)) public _deposits;
    address payable payee = payable(msg.sender);
    address tokenaddress = 0x...;
    MyToken token = MyToken(tokenaddress);

    function deposit(uint256 amount) public payable {
        token.approve(msg.sender, address(this), amount);
        token.transferFrom(msg.sender, address(this), amount);
        _deposits[payee][tokenaddress] += amount;
    }

    function depositsOf() public view returns (uint256) {
        return _deposits[payee][tokenaddress];
    }

    function withdraw(uint256 payment) public payable {
        _deposits[payee][tokenaddress] -= payment;
        token.transfer(msg.sender, payment);
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.