0

I have a user, Contract A, and Contract B. I want user to call a function A of Contract A, that function executes function B from Contract B, which sends ether from Contract B to Contract A.

Here is my test:

let eco_fac = await ECOFactory.deployed()
let buyer = accounts[1]
let eco_address = await eco_fac.getEco(buyer)
let _eco = await ECO.at(eco_address)
let fund_or_exercise = await _eco.exercise({from: buyer})

Here is my exercise function of Contract A:

@public
@payable
def exercise() -> bool:
    if(msg.sender == self.seller):
        log.Error('Exercise Call must be from Buyer')
        return False
    if(msg.sender == self.buyer):
        """
        This is where cash dispersement is handled.
        ECO tx -> Vendor: withdraw(strike amount)
        ECO tx -> Vendee: deposit(strike amount)
        ECO tx -> Vendee: withdraw(spot amount)
        ECO tx -> Vendor: deposit(spot amount)
        ECO deactivated and completed
        return True
        """
        val: wei_value = as_wei_value(1, 'ether')
        log.Exercise(self.buyer, self, True)
        #elf.vendor.pay(val)
        self.vendor.withdraw(self.vendor, val)


        return self.vendor.authorizedEco(self.vendor, self)
    else:
        log.Error('Exercise attempt returns False')
        return False

Here is my withdraw function of Contract B:

@public
def withdraw(addr: address, amount: wei_value) -> bool:
    if(amount > self.balance):
        log.Error('Exceeds balance')
        return False
    if(self.authorized[addr]):
        log.AccountWithdrawal(addr, addr, amount, True)
        log.Error('Authorized, continue to withdraw')
        send(msg.sender, amount)
        return True
    log.Error('Withdraw Unsuccessful, User Unauthorized')
    return False

My code executes correctly into the

if(self.authorized[addr]):

code block, but when I call send(msg.sender, amount) is when I get a VM exception revert. The withdraw function works for everything but the Contract A address it seems. Not sure how to work this out.

In the exercise function I can do this:

send(self.vendor, val) 

and it will still revert.

  • Does your contract have a fallback function? Default function in vyper parlance vyper.readthedocs.io/en/v0.1.0-beta.13/…. – Ismael Nov 9 at 22:41
  • @Ismael yes, both contracts have the default fallback function – isomotic Nov 9 at 22:43
  • @Ismael maybe I need to increase the gas stipend? If so, how can I do that? – isomotic Nov 9 at 22:49
  • They mention you have to use call in the documentation. It appears it refers to raw_call. Also I suggest to read Consensys report about vyper security issues diligence.consensys.net/blog/2019/10/…. – Ismael Nov 10 at 3:45
  • 1
    @Ismael Thank you for linking that, I'll take a look at it. I found my solution: don't use account contract proxies. My workaround is just letting the users withdraw unclaimed balances from the ECO contract. – isomotic Nov 10 at 4:01

Your Answer

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

Browse other questions tagged or ask your own question.