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

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.

| improve this answer | |
  • 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 '18 at 4:36
  • @MaxFL revised answer – Miguel Mota Feb 2 '18 at 7:16
  • is it safe to use txn.destination.call.value(txn.value)(txn.data) ? – Ender Apr 1 '19 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. – Miguel Mota Apr 1 '19 at 15:32

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.