This question is an extension of this previous question where this commit of this Pull Request I used a modified version of this ink! basic-contract-caller example where there is a BasicContractCaller main contract and a OtherContract sub-contract.

But this question relates to changes I made to that code by using the Builders approach section's CreateBuilder and CallBuilder as mentioned in the ink! documentation here.

The Builder approach that I implemented is in this commit.

To run it, I follow the steps in the README file and then after entering the Docker container I run cd /app && ./docker/quickstart-basic-contract-caller.sh and it runs through these steps:

  1. Starts a fresh local node using substrate-contracts-node
  2. Builds both of those contracts
  3. Uploads both of those contracts
  4. Instantiates both of those contracts with cargo contract instantiate --manifest-path $PARENT_DIR/dapps/basic_contract_caller/Cargo.toml --suri //Alice --constructor new --args $CODE_HASH_SUB $CONTRACT_ADDR_SUB --execute --gas 200000000000 --proof-size 100000000000 --skip-confirm. Note: It was necessary to provide more gas --gas 200000000000 otherwise I got error The executed contract exhausted its gas limit. Note: It was also necessary to use .endowment(0), otherwise I got error Cross-contract instantiation failed with TransferFailed.
  5. Calls a setter method flip() in the sub-contract directly cargo contract call --suri //Alice --contract $CONTRACT_ADDR_SUB --message get --execute --gas 200000000000 --proof-size 100000000000 --skip-confirm
  6. Calls a getter method get() in the sub-contract directly with cargo contract call --suri //Alice --contract $CONTRACT_ADDR_SUB --message get --execute --skip-confirm
  7. Calls a method get() in the main contract that calls a getter method get() in the sub-contract cargo contract call --suri //Alice --contract $CONTRACT_ADDR_MAIN --message get --execute --skip-confirm.

Based on that ink! documentation I thought it was necessary to remove use of Contract Ref from the Contract References Approach if I was going to use the Builder approach instead, however I was not able remove having to import the sub-contract that I want to call as a dependency of the main contract since in the documentation here it seems necessary to provide the Contract Ref in the Builder Approach implementation example like this build_create::<OtherContractRef>().

Whilst I was able to get the above steps 0-5 to work, I wasn't able to solve the previous question, and I got errors running step 6, which calls the sub-contract via the main contract, since it outputs:

Calling contract method get ...
ERROR: Pre-submission dry-run failed. Use --skip-dry-run to skip this step.

And I then ran it with --skip-dry-run as the error suggests I do by adding these additional options here:

    --gas 200000000000
    --proof-size 100000000000

then instead it outputs the below error, which based on this question, which indicates that a panic has occurred, but in that get() method in the main contract here I feel like I'm already handling errors appropriately, and the get() method it should call in the sub-contract is basic as shown here.

Calling contract method get ...
ERROR: ModuleError: Contracts::ContractTrapped: ["Contract trapped during execution."]

How would I fully remove using Contracts Ref now that I'm using the Builders Approach incase that is the cause of the error??

Note: Unfortunately it doesn't seem possible to debug using this Builder Approach though. They highlight this limitation in the ink! documentation You will not be able to get any feedback about this at at compile time. You will only find out your call failed at runtime!.

1 Answer 1


I do not think resolving the error ContractTrapped needs Contracts Ref to be fully removed when using the Builders Approach.

I tried using try_invoke() instead of invoke() here as suggested in the ink! documentation here and that improved feedback at compile time. Instead of the previous error ContractTrapped that was not helpful, it gave the error shown below that suggested it was transfer related:

DEBUG tokio-runtime-worker runtime::contracts: Execution finished with debug buffer: my_return_value Err(TransferFailed)
error TransferFailed

So in the main contract I changing it from .transferred_value(10) to .transferred_value(0) and that resolved the TransferFailed error.

I only used .transferred_value(10) because they use that non-zero value in the CallBuilder example here, but I do not know how it is possible to get a non-zero value to work.

I was only able to get it to work using a value of 0 in .transferred_value(0), but not with any larger number, even if I added payable in my code here or with #[ink(message, payable)] to the flip() method in the sub-contract that I was calling via the main contract, as mentioned in the ink! documentation here.

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.