2

Please tell me how can smart contract call it's own function if this is not in smart contract code? Here is an example: https://github.com/gnosis/MultiSigWallet/blob/master/contracts/MultiSigWallet.sol. It has onlyWallet modifier applied to addOwner function, but addOwner is not called in the code. Thanks.

1 Answer 1

1

The line require(msg.sender == address(this)) in onlyWallet can be a bit of a head scratcher, so let's first look at some snippets from the MultiSig wallet tests to see how you'd interact with the contract:

var owners = [accounts[0], accounts[1], accounts[2]]
var multisigInstance = await MultiSigWallet.new(owners, confirmations)
var addOwnerData = multisigInstance.contract.addOwner.getData(accounts[3])
await multisigInstance.submitTransaction(multisigInstance.address, 0, addOwnerData, {from: accounts[0]})

As you can see, one of the contract owners can invoke submitTransaction passing along the encoded data that makes up the addOwner method call.

Inside the submitTransaction smart contract method there is a call to the addTransaction method which stores the transaction data (addOwners call data) into a mapping.

transactions[transactionId] = Transaction({
    destination: destination,
    value: value,
    data: data,
    executed: false
});

Then an owner calls the confirmTransaction method to confirm the transaction which then invokes executeTransaction(transactionId):

Finally, inside executeTransaction you can see that it's executing the encoded data (addOwner call data) which makes the contract address the sender:

txn.destination.call.value(txn.value)(txn.data)

So essentially, the MultiSig wallet allows owners to submit a transaction which gets stored until another owner approves of it and executes it.

4
  • General scheme of the function calls is clear. In this particular example we have onlyWallet modifier for the method addOwner. This modifier requires the caller to be the contract. So how contract can call it's own function if it's not called in the contract code?
    – Max FL
    Feb 2, 2018 at 4:36
  • @MaxFL revised answer Feb 2, 2018 at 7:16
  • is it safe to use txn.destination.call.value(txn.value)(txn.data) ?
    – Ender
    Apr 1, 2019 at 9:09
  • 1
    @Ender yes it’s safe; basically it’s used when you don’t know or have the interface of the contract you’re calling but just know that that method exists. Apr 1, 2019 at 15:32

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.