0

I have two contracts, 0xA and 0xB, and they both have an attribute 'mate_address' which is the other contracts address. For instance, 0xA's mate_address is 0xB, and 0xB's mate_address is 0xA.

I want to define a function which can be called by any address, in this case 0xC, which will send the balance of one contract to another.

Here are the contracts:

0xA:

contract TheContract {
    address public mateAddress = OxB

    function () payable public {
        if (msg.sender == mateAddress) {
            //do something
        }
    }

    function checkStatus() {
        if (someCondition) {
            address myAddress = this;
            mateAddress.send(myAddress.balance);
        }
    }
}

0xB:

contract TheContract {
    address public mateAddress = OxA

    function () payable public {
        if (msg.sender == mateAddress) {
            //do something
        }
    }

    function checkStatus() {
        if (someCondition) {
            address myAddress = this;
            mateAddress.send(myAddress.balance);
        }
    }
}

When I try to call the checkStatus function, my transaction gets reversed at the if (msg.sender == mateAddress) line.

How could i get the behaviour that I want?

  • The someCondition is if (msg.sender == mateAddress) ? – Eli Drion Apr 4 '18 at 8:14
  • is the function definition correct? you have function () checkStatus instead of function checkStatus() – Jaime Apr 4 '18 at 8:42
1

Let's assume you execute checkStatus in contract A. If the someCondition is fulfilled, you will send the balance of A to B. The payable function will revert because the gas sent using mateAddres.send() is not enough to execute anything else but the transaction (I had this issue a few weeks ago). You can solve this defining the payable function with an argument.

contract TheContract_A {
    address public mateAddress = OxB

    function funding(address from) payable public {
        if (from == mateAddress) {
            //do something
        }
    }

    function () checkStatus {
        if (someCondition) {
            TheContract_B instanceOfB = TheContract_B(mateAddres);
            instanceOfB.funding.value(address(this).balance)(address(this));
        }
    }
}

contract TheContract_B {
    address public mateAddress = OxA

    function funding(address from) payable public {
        if (from == mateAddress) {
            //do something
        }
    }

    function () checkStatus {
        if (someCondition) {
            TheContract_A instanceOfA = TheContract_A(mateAddres);
            instanceOfA.funding.value(address(this).balance)(address(this));
        }
    }
}

What I have done is to make an interaction between the contracts. A will call the funding function (payable) in B with an argument which will increase the allowed gas, then you can execute more code in this call. The same for contract B.

This line:

TheContract_B instanceOfB = TheContract_B(mateAddres);

creates an instance of B in A to be able to access B functions, and this line:

instanceOfB.funding.value(address(this).balance)(address(this));

will execute the funding function in B including a transaction of ether from A with value address(this).balance

As for the reason of the gas limit you will read in the docs (solidity)

address.transfer(uint256 amount): send given amount of Wei to Address, throws on failure, forwards 2300 gas stipend, not adjustable.

address.send(uint256 amount) returns (bool): send given amount of Wei to Address, returns false on failure, forwards 2300 gas stipend, not adjustable

Is not the same when the ether is sent from an account. In the transfer from Ether from an account you can send more gas.

Also, slightly unrelated, I think is safer to use transfer rather than send in future contracts.

I hope this helps.

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.