I want to move the Solidity ERC20 token from one third party to another, but I get an error.

Asked 2 years ago, Updated 2 years ago, 92 views

Me: A
ERC20 tokens:Coin
ERC20 tokens:Fund
Deployer for both tokens is the same account: Z
counterpart:B

I want to move the same amount of Coin from Z to B when A burns the Fund
"If you send ""thank you"" from A to B, you will receive a coin from Z to B."

The development is done with Remix's VM

Solidty for Coin

//SPDX-License-Identifier: GPL-2.0
pragma solidity^0.6.0;

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

contract Coin is ERC20 {
    address private_MakerAddress;
    US>//#string private_Message=";
    US>string public version;

    constructor(
        US>string memory name,
        string memory symbol,
        uint256 initial_supply,
        US>string memory version_
    ) public ERC20(name, symbol){
        _MakerAddress=msg.sender;
        _mint(msg.sender, initial_supply);
        version=version_;
    }

    function addCoin(uint256amount)public returns(uint256){
        _mint(msg.sender, amount);
    }

    function transferWithMessage(address recipient, uint256amount, string memory message) public payable returns(bool) {
        _Message=message;
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    function getMakerAddress()public view returns(address){
        return_MakerAddress;
    }
}

Fund Solidty

//SPDX-License-Identifier: GPL-2.0
pragma solidity^0.6.0;

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

contract FundManager is ERC20 {
    address private_MakerAddress;
    US>//#string private_Message=";
    US>//#string private_version=";
    address payable private_coinTokenOwner;
    IERC20 private_coinToken;

    event Realize(uint256amount, address receiver, string message);

    constructor(
        US>string memory name,
        string memory symbol,
        uint256 initial_supply,
        string memory version,
        address payable coinTokenOwner,
        IERC20 coinToken
    ) public ERC20(name, symbol){
        _MakerAddress=msg.sender;
        _mint(msg.sender, initial_supply);
        _version=version;
        _coinTokenOwner=coinTokenOwner;
        _coinToken=coinToken;
    }

    function addFund(uint256amount) public returns(uint256){
        _mint(msg.sender, amount);
    }

    function getVersion()public view returns(string memory){
        return_version;
    }

    function getMakerAddress()public view returns(address){
        return_MakerAddress;
    }

    function realize(uint256_amount, address_receiver, string memory_message)public{
        permit Realize(_amount,_receiver,_message);
        super._burn(msg.sender,_amount);
        _coinToken.approve(_coinTokenOwner,_amount);
        _coinToken.transferFrom(_coinTokenOwner,_receiver,_amount);
    }
}

realize is a function that I want to burn the fund and send money

It works from Z to A, but when A executes realize, the following error occurs

transact to FundManager.realize error:VM error: revert.revert The transaction has been reversed to the initial state. Reason provided by the contract: "ERC20:transfer amount exceeds allowance".Debug the transaction to get more information.

transferFrom can be used for third-party remittance, but is it wrong to use it?

I'm starting to think that it's technically impossible to move someone else's token on my own request while making it myself.
I would appreciate it if you could give me an idea in that case.

Additional information
As the description method was pointed out, this is a summary.

I reconsidered FundManager
(I have removed part of Burn so that I can run it many times in the test.)

//SPDX-License-Identifier: GPL-2.0
pragma solidity^0.6.0;

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

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

contract FundManager is ERC20 {
    address private_MakerAddress;
    US>//#string private_Message=";
    US>//#string private_version=";
    address private_coinTokenOwner;
    IERC20 private_coinToken;

    event Realize(uint256amount, address receiver, string message);

    constructor(
        US>string memory name,
        string memory symbol,
        uint256 initial_supply,
        string memory version,
        address coinTokenOwner,
        IERC20 coinToken
    ) public ERC20(name, symbol){
        _MakerAddress=msg.sender;
        _mint(msg.sender, initial_supply);
        _version=version;
        _coinTokenOwner=coinTokenOwner;
        _coinToken=coinToken;
    }

    function realizeAllowance(uint256_amount, address_receiver, string memory_message)public returns(bool){
        require(_amount>0);
        require(_receiver!=address(0);

        permit Realize(_amount,_receiver,_message);

        _coinToken.allowance(_coinTokenOwner,_receiver);

        return true;
    }

    function realizeApproval(address_receiver, uint256_amount)public returns(bool){
        require(_amount>0);
        require(msg.sender!=address(0);

        _coinToken.approve(_receiver,_amount);
        return true;
    }

    function realizeTransferFrom(address_receiver, uint256_amount)public returns(bool){
        require(_amount>0);
        require(msg.sender!=address(0);
        require(_receiver!=address(0);

        _coinToken.transferFrom(_coinTokenOwner,_receiver,_amount);

        return true;
    }
}

realizeAllowanceRun as yourself(A)
realizeApprovalRun as Owner(Z)
realizeTransferFromRun as yourself(A)

realizeApprovalI thought I was running it as Owner(Z), but it was running from Fund, so it was the address of Fund.
owner:Fund address
spender:B
I got a value when I ran it in
Is it wrong to approve from Fund?

I hope it will be helpful

ethereum solidity

2022-09-30 14:25

1 Answers

I reviewed various things and worked with the following contents.
I haven't put in the Burn part yet, but

//SPDX-License-Identifier: GPL-2.0
pragma solidity^0.6.0;

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

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

contract FundManager is ERC20 {
    address private_MakerAddress;
    US>//#string private_Message=";
    US>//#string private_version=";
    address private_coinTokenOwner;
    IERC20 private_coinToken;

    event Realize(uint256amount, address receiver, string message);

    constructor(
        US>string memory name,
        string memory symbol,
        uint256 initial_supply,
        string memory version,
        address coinTokenOwner,
        IERC20 coinToken
    ) public ERC20(name, symbol){
        _MakerAddress=msg.sender;
        _mint(msg.sender, initial_supply);
        _version=version;
        _coinTokenOwner=coinTokenOwner;
        _coinToken=coinToken;
    }

    function addFund(uint256amount) public returns(uint256){
        _mint(msg.sender, amount);
    }

    function getVersion()public view returns(string memory){
        return_version;
    }

    function getMakerAddress()public view returns(address){
        return_MakerAddress;
    }

    function realize(uint256_amount, address_receiver, string memory_message)public returns(bool){
        require(msg.sender!=address(0);
        require(_amount>0);
        require(_receiver!=address(0);

        permit Realize(_amount,_receiver,_message);

        _coinToken.allowance(address(this),_receiver);
        _coinToken.approve(_receiver,_amount);
        _coinToken.transfer(_receiver,_amount);

        return true;
    }
    
    function getCoinBalance() public view returns(uint256) {
        return_coinToken.balanceOf(address(this)));
    }
}

The problem seems to have started with not knowing that when accessing a smart contract from a smart contract, the address becomes the address of the smart contract, not the address at runtime.

I would appreciate it if you could point out any security issues.

Thank you very much


2022-09-30 14:25

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.