0

I have two methods: sendfromself() and getbalance()

The only difference is that the first method, checks if the msg.sender has any coins in the ERC20 address supplied in the method's arguments, and if so, transfers that balance to the contract.

The second method, checks if the contract has any ERC20 coins and if so, transfers these coins to a nominated address.

Strangely the second method works, the first one sendfromself() does not. For the avoidance of doubt, I have invoked the ERC20 approve() method with the address of this contract.

What am I doing wrong? Why doesn't the first method send me msg.sender's ERC20 coins?

from vyper.interfaces import ERC20


event balancex:
    balancex: uint256
    
other: constant(address) = 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db


@payable
@external
def sendfromself(_coin: address) -> bool:

    amount: uint256 = ERC20(_coin).balanceOf(msg.sender)
    log balancex(amount)
    if amount > 0:
        ERC20(_coin).transferFrom(msg.sender, self, amount)
    return True

@payable
@external
def getbalance(_coin: address) -> bool:

    amount: uint256 = ERC20(_coin).balanceOf(self)
    response: Bytes[32] = raw_call(
        _coin,
        concat(
            method_id("transfer(address,uint256)"),
            convert(other, bytes32),
            convert(amount, bytes32),
        ),
        max_outsize=32,
    )
    if len(response) != 0:
        assert convert(response, bool)

    return True
2
  • Can't find anything wrong in the body of the first function. Maybe there is an requirement from this erc20 token that if this token is send to a contract, it needs to apply to an interface, so the tokens can get send from the receiving contract again. But that is just a wild guess. And erc20(coin).balanceOf(contract address) returns 0?
    – Maxstgt
    Commented Oct 2, 2021 at 11:25
  • I'm using the standard ERC20 Vyper implementation: github.com/vyperlang/vyper/blob/master/examples/tokens/ERC20.vy can you kindly take a look and let me know? When you say "if this token is sent to a contract it needs to apply to an interface" what do you mean? How would the code change? Commented Oct 2, 2021 at 11:42

2 Answers 2

0

For transferFrom(from, to, amount) to work, the calling address (msg.sender) need to have enough token allowance assinged by the from address, even if the from address was the calling address itself. This might be counter-intuitive, as why should the calling address have approval to use its own token balance? But apparently that's how ERC20 is implemented. So you should proceed this line with:

ERC20(_coin).approve(msg.sender, amount)
1
  • Thank you for your answer - this still appears to not work - transact to foo.sendfromself errored: VM error: revert. revert The transaction has been reverted to the initial state. Note: The called function should be payable if you send value and the value you send should be less than your current balance. Debug the transaction to get more information. Commented Oct 2, 2021 at 11:52
0
from vyper.interfaces import ERC20


event balancex:
    balancex: uint256
    
other: constant(address) = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2

@external
def sendfromself(_coin: address) -> bool:
    amount: uint256 = ERC20(_coin).balanceOf(msg.sender)
    allowance: uint256 = ERC20(_coin).allowance(msg.sender,self)
    
    if (allowance == 0):
        return False
    
    if (allowance < amount):
        return False
    
    else:
        if (allowance >= amount):
            ERC20(_coin).transferFrom(msg.sender,self,amount)
            log balancex(amount)
            return True
        else:
            return False



@external
def getbalance(_coin: address) -> bool:

    amount: uint256 = ERC20(_coin).balanceOf(self)
    response: Bytes[32] = raw_call(
        _coin,
        concat(
            method_id("transfer(address,uint256)"),
            convert(other, bytes32),
            convert(amount, bytes32),
        ),
        max_outsize=32,
    )
    if len(response) != 0:
        assert convert(response, bool)

    return True



The above code seems to now work well. Had to have a check on the allowance

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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