0

I'm trying to inherit and override a parent's payable function (and adding some modifier and logic) but so far seem unable to do so.

My first intuitive try was something like this:

contract foo {
    function test() public payable returns (uint256) {
        return msg.value;
    }
}

contract bar is foo {
    function test() public payable returns (uint256) {
        return super.test.value(msg.value / 2)();
    }
}

and received compile error:

TypeError: Member "value" not found or not visible after argument-dependent lookup in function () - did you forget the "payable" modifier?
    super.test.value(msg.value)();

Give the function a different name doesn't work either so it's not an overriding issue.

contract foo {
    function test() public payable returns (uint256) {
        return msg.value;
    }
}

contract bar is foo {
    function anotherTest() public payable returns (uint256) {
        return super.test.value(msg.value / 2)();
    }
}

I got slightly further by tricking compiler with a casting but this is obviously no good as would cause infinite loop at runtime:

contract foo {
    function test() public payable returns (uint256) {
        return msg.value;
    }
}

contract bar is foo {
    function test() public payable returns (uint256) {
        return foo(address(this)).test.value(msg.value / 2)();
    }
}

What works is combining the two, i.e. giving it a different name and casting:

contract foo {
    function test() public payable returns (uint256) {
        return msg.value;
    }
}

contract bar is foo {
    function anotherTest() public payable returns (uint256) {
        return foo(address(this)).test.value(msg.value / 2)();
    }
}

Now calling bar.test() with 6 wei returns 6 and calling bar.anotherTest() returns 3. But this isn't exactly what I want as it still exposes test() through bar.

So what am I doing wrong, or is this by design? Would really like to understand why Solidity behave this way and if there's a workaround to achieve what I want. thanks!

1 Answer 1

0

Since foo is the base contract of bar when you call super.test() you are calling yourself within the same contract.

Now your are trying to send yourself half of msg.value and the other half will still be in your contract.

I'd recommend to pass the desired value as parameter of the function.

1
  • Yeah, I eventually figured it out. As you explained, I'm calling within the same contract and there's really no reason to resend ether to the same pocket, simply calling super.test() without .value or with a parameter would do. Thanks!
    – jhuang
    Aug 2, 2018 at 4:13

Your Answer

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

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