Contract.ContractTrapped

Hi all, i ran into problem when deploying contract to Shibuya testnet, bellow is the discription:

1、Use Solang compile solidity contracts to wasm bytecode
2、Deploy xxx.contract to Shibuya testnet
3、Call contract interface but failed with “Contract.ContractTrapped”, the error caused by when new a contract from inside of the deployed contracts

So is the error related to the Shibuya substrate wasm?

1 Like

@bLd759 @tomasz-waszczyk

Please help this case.

Could you show source code of the contract you want to deploy? In that way will be easier to catch your problem. What version of Solang do you use? Give more information.

Check bellow code snippet

Solang version v0.1.10-84-g233920a1
docker run --rm -it -v $(pwd):/sources Package solang · GitHub -v -o /sources --target substrate /sources/test.sol

pragma solidity >=0.6.0;

contract Base{
constructor() payable{}
}

contract Test{

    constructor() payable{}

    function createNew() public  {
            new Base();
    }

}

===========================
call createNew shall raise “Contract.ContractTrapped”

In order to improve a source code I have added a required public modifiers, here you can look at the code deployed on Shibuya network: Base (0x8c44562d38d3dB30F0619c93B258a290C7351B69) - Shibuya (EVM) Explorer

pragma solidity 0.6.0;

contract Base{
    constructor() payable public{}
}

contract Test{

    constructor() payable public{}

    function createNew() public  {
        new Base();
    }
}

Proof of Verification:

Here you can find helpful article how to verify smart contracts: Verifying a Smart Contract - Blockscout

Thx tomasz, actually the above snippet can work in EVM-module, but failed in substarte wasm-model, plz check in substarte wasm when u free

1 Like

OK, I see. So it is a bit longer story, but I have found quite fast way to deliver deployment of your smart contract.

Assumption: I use Linux Mint and/or Linux Debian, verified on both, it works.

You are required to have Solang, the fastest way is to download from Github: GitHub - hyperledger-labs/solang: Solidity Compiler for Solana, Substrate, and ewasm, then give execution permission on exactable file - chmod +x solang-linux-x86-64.

In order to compile smart contracts, you need to execute following command: ./solang-linux-x86-64 --target substrate Base.sol

My output looks like below:

Then in the directory where you have compiled a smart contract you should have following list of files:

image

Then go to PolkadotJS Developers section: Polkadot/Substrate Portal and select Base.contract file:

Then you are ready to make a deployment, confirm transaction and you should get:

Here are helpful links although I see that they are not up to date:

  1. Compile smart contracts written in Solidity to WASM on Windows | by Maarten Henskens | Plasm Network | Medium | Astar Network
  2. Installing Solang — Solang Solidity Compiler v0.1.11-3-g33429c5 documentation
  3. Solidity to WASM Compiler - Astar & Shiden documentation

I have shown you the fastest way how to make a deploy. More extensive way is to use Docker, but it works a bit different on different OS, that is way I shown the way that just should work. To make all working I have edited a bit a smart contract:

image


pragma solidity 0.6.0;

contract Base{
    constructor() payable public{}
}

contract Test{

    constructor() payable public{}

    function createNew() public  {
        new Base();
    }
}

Thx tomasz, here is my story:

1、 Deploy Test contract using Test.contract abi into Shibuya network via Polkadot/Substarte Portal as you mentioned above
2、exec “createNew” of Test contract via Polkadot ui failed with “Contract.ContractTrapped” error

I’m pretty sure the error is caused by the expression “new Base()”, so i want to to know why this case will happen since it works normal in EVM-model. I’m not sure if it’s related to Shibuya substrate-runtime (mybe not support create new contract in an existed one ) or the solang compiler itself (has some issues to compile solidity into wasm-bytecode), can u help me check if the Shibuya testnet support the feature that can create a contract inside of an existed one that just like the expression “new Base”?

1 Like

I think that the solution for the issue could be passing in constructor or createNew function of Test smart contract hash of a previously deployed Base smart contract. Exactly speaking you will call createNew () function, and as a parameter of the function will be a hash of previously deployed Base contract. Have you tried it? Or even simpler, something like that:

// SPDX-License-Identifier: MIT
// Specifies the version of Solidity, using semantic versioning.
// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma

pragma solidity 0.7.0;

contract Base{
    constructor() payable {}
}

contract Test{
    function createNew() payable public  {
        Base base = new Base();
    }
}

I think the simplest solution could be using internal function:

Internal functions can only be accessed from within the current contract or contracts deriving from it. They cannot be accessed externally. Since they are not exposed to the outside through the contract’s ABI, they can take parameters of internal types like mappings or storage references.

Source: Contracts — Solidity 0.8.13 documentation

It depends what you exactly want to do, if having one file is good enough I recommend applying internal, at least I do not know any better solution. If not, you need to try to call a smart contract externally using hash.

PS. OK, I have done it on my own machine. Firstly, check whether your smart contract looks like my, above. Then remember to add SBY to transaction:

I have made a video, I have added also payable decorator (it is important) to the smart contract:

Please write me a feedback, because on my end works and will be helpful to me that I knew that someone was able to deploy the smart contract. Do exactly like I have done it on a video, and you should be fine.

Hi tomasz,
It works according to your revised code which added a modifier “payable” to the “createNew”.

Then i added some codes for more test, but failed again, bellow is new changes:

pragma solidity 0.7.0;

contract Base{
   string state; // added a state var
    constructor() payable {}
}

contract Test{
   Base base;
    function createNew() payable public  {
        base = new Base{value:2*10**10, gas:2*10**10, salt:0}();
    }
}

=======================================



then call ‘createNew’ with above deployed contract failed again, the error is the same “Contract.ContractTrapped”.

Plz kindly help me to find out whats’s wrong with the above snippet.

Strange. For me it works, have you added SBY to the transactions? Look at the video, what is the difference?

PS. Sorry for that visual noises at the top of recording, I am in the process of migration to newest XFCE. If you have some concrete goal you want to achieve, say openly, in my free time I try to do it and write an article with solution (as far as my skills allows me to do it).

1 Like

Thx tomasz for your great effort. I follow the video and tried again, but still failed(‘has added SBY to transactions’). I’ll double check what difference between you and my env.
BTW, can you tell me the solang version used for compiling?

I have checked it once more time, and for me works. Hmmm, I use the client: Polkadot/Substrate Portal

@james Does it work for you? I am curious :wink:

Hi tomasz,

Sorry my fault, the code i used has slight difference with yours.

pragma solidity 0.7.0;

contract Base{
   string **public** state; // added a state var
    constructor() payable {}
}
contract Test{
   Base base;
    function createNew() payable public  {
        base = new Base{value:2*10**10, gas:2*10**10, salt:0}();
    }
}

I added ‘public’ to the name field of Base contract, which should be the root cause that making the call failed, since i make the bellow test:
1、remove “public” then the call “createNew” success
2、add back “public”, the call failed
3、remove away again, the call success

BTW, i have made bellow test to verify if added more public interface to the “Base” will cause “createNew” failed:

contract Base{
   string  state; // added a state var
    constructor() payable {}

    function sum(uint a, uint b) public pure returns(uint){
        return a + b;
   }
}

contract Test{
   Base base;
    function createNew() payable public  {
        base = new Base{value:2*10**10, gas:2*10**10, salt:0}();
    }
}

Above version with bellow changes:
1、remove “public” access modifier
2、add new interface “sum”

But when i call “createNew”, the above case failed.

BTW, i have no ideal on how the contract will’be failed, could you give me some tips or tutorials.

Thx a lot
:pray: :pray:

Have you tried to compile this contract?
This is error on Remix:

from solidity:
ParserError: Function, variable, struct or modifier declaration expected.
 --> contracts/bla.sol:9:1:
  |
9 | contract Test{
  | ^^^^^^^^
```

I also got an error while trying to compile the smart contract you have shown in Remix. You should not expect that contract which is not compile-able in Remix will work/compile in WASM mode. Firsly, is required fully working code in Remix.

image

contract Base{
   string  state; // added a state var
    constructor() payable {}

    function sum(uint a, uint b) public pure returns(uint){
        return a + b;
   }
} // please add up

contract Test{
   Base base;
    function createNew() payable public  {
        base = new Base{value:2*10**10, gas:2*10**10, salt:0}();
    }
}

Sorry to make you confused, a “}” is missing from the contract Base, please add up to have a test.

It is easier to understand me your issue while I have the exact code you have. OK, so let’s solve your issue. You are facing with an issue of overflowing of integers in Solidity language. While you want to add values, we need to implement it very carefully, below is the same logic, but a bit different implemented:

pragma solidity 0.8.0;

contract Base{
    string state; //added a state var
    constructor() payable {}

    function sum(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);
        return c;
    }
}

contract Test{
    Base base;
    function createNew() payable public  {
        base = new Base();
    }
}

While you want to add values, just use the SafeMath library method to keep your code more safe.

Description of an issue from Rust perspective: ink-docs/faq.md at master · paritytech/ink-docs · GitHub

Here you can look at how those operations are implemented in well-known Open Zeppelin library: openzeppelin-contracts/SafeMath.sol at master · OpenZeppelin/openzeppelin-contracts · GitHub

Let me know whether does it work for you.

Thx tomasz for your patiently explanation. Acctually, i want to figure out why the “public” or “external” access modifier applied for “sum” or other interfaces of Base shall cause the “new Base()” statement failed. But it’s OK in EVM. Plz have a try when you free.

BR

Could you tell me, what have you done personally to answer your question? Have you tried to experiment with the code and search in documentation?