3

When working with smart contracts in Contracts UI you sometimes need to call a message as the contract itself. For example the addOwner message of the Multisig ink! example.

How can I add the contract to my wallet or to the @polkadot/keyring in order to be able to sign an extrinsic?

enter image description here

3 Answers 3

4

There is no (known) secret key for a contract's account id. This is kind of the point of contracts: Their actions are governed by code rather than by an external force that can provide a signature.

There can't be a signature that is provided by a contract ever. The only way to have a specific contract appear as a caller somewhere is to make this contract execute the call. How do you do that? That depends completely on the contract in question. That is: Is the contract coded in a way to allow the interaction you want? The answer is usually "yes" because the contract author had a specific workflow in mind when putting the requirements in place.

In your concrete example we require the contract itself to call add_owner because it is a privileged operation. Those must only be performed if enough owners want it to happen. If this is the case they can act on behalf of the contract (this is the basic multisig functionality). They do that by submitting a transaction that adds an owner, approve it and finally execute it. The workflow would look like this:

  1. Encode a Transaction that calls add_owner and pass it to submit_transaction. Please note that you need to set allow_reentrancy to true as the contract will be calling itself.
  2. Make enough owners call confirm_transaction on the TransactionId returned by your call to submit_transaction in step 1.
  3. Call invoke_transaction on the TransactionId. This will make the contract call add_owner on itself.

Crafting the Transaction in step 1 requires the metadata in order to look up the selector and how to encode inputs. It is also a manual process. I think it would be worthwhile to standardize a Call type in the contract metadata so that a nice UI could be build in case a call needs to be passed as argument.

3

The contract's address (i.e. AccountId) is derived through an AddressGenerator in pallet-contracts.

This AddressGenerator is configurable. At the time of writing this, the default is here:

hash("contract_addr_v1" ++ deploying_address ++ code_hash ++ input_data ++ salt)

As you can see, the deploying_address (for which the deployer has the private key) gets mixed with other information. For this new AccountId (i.e. public key) there can not be a known private key.

2

It is not possible to add a contract to a wallet. For this specific example where the multisig wallet (i.e. the contract) has to call the contract, you'd have to make a cross contract call. To do this in the contract UI you'd have to make another smart contract that makes this cross contract call to the multisig wallet.

2
  • some messages have a constraint that the caller needs to be the contract account itself. i am talking about those cases. see addOwner message on the multisig example i linked in my question Mar 30, 2023 at 12:48
  • Misunderstood your question, I edited my answer. Mar 31, 2023 at 8:05

Your Answer

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

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