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?
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.
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:
pragma solidity 0.6.0;
contract Base{
constructor() payable public{}
}
contract Test{
constructor() payable public{}
function createNew() public {
new Base();
}
}
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”?
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.
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}();
}
}
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).
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?
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.
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.
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.
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.