Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can not deploy a contract #3268

Closed
bakasura980 opened this issue Mar 5, 2021 · 9 comments
Closed

Can not deploy a contract #3268

bakasura980 opened this issue Mar 5, 2021 · 9 comments
Labels

Comments

@bakasura980
Copy link

When I am trying to deploy a contract doing the process described in the documentation, some of the functions are deprecated.
That being said here is the way I am trying to deploy a contract

const code = new ContractUtils.CodePromise(api, ABI, WASM)
await code.tx.new({ gasLimit: 100000 * 1000000, salt: null, value: 1230000000000 }, ALICE.address).signAndSend(ALICE)

This results in an error saying "Cannot read property 'batch' of undefined". The "batch" function behind the scene is called
in Code.js row 90 like so

return this.api.tx.utility.batch....
@vminkov
Copy link
Contributor

vminkov commented Mar 7, 2021

This works:

describe('Deploy contract', async () => {
    it('should deploy a contract', async () => {
        const contractWasm = await readFile(wasmPath).then(json => JSON.parse(json)).catch(() => null);
        const contractAbi = await readFile(abiMetadataPath).then(json => JSON.parse(json)).catch(() => null);

        const wasm = contractWasm.source.wasm;
        const code = new CodePromise(api, contractAbi, wasm);

        const keyring = new Keyring({ type: 'sr25519', ss58Format: 42 });
        const bob = keyring.addFromUri('//Bob', { name: 'Bob default' });
        const { nonce, data: balance } = await api.query.system.account(bob.address);
        const now = await api.query.timestamp.now();
        console.log(`${now}: ${bob.address} has balance of ${balance.free} and a nonce of ${nonce}`);

        // Subscribe to system events via storage
        api.query.system.events((events) => {
            console.log(`\nReceived ${events.length} events:`);

            // Loop through the Vec<EventRecord>
            events.forEach((record) => {
                // Extract the phase, event and the event types
                const { event, phase } = record;
                const types = event.typeDef;

                // Show what we are busy with
                console.log(`\t${event.section}:${event.method}:: (phase=${phase.toString()})`);
                console.log(`\t\t${event.meta.documentation.toString()}`);

                // Loop through each of the parameters, displaying the type and data
                event.data.forEach((data, index) => {
                    console.log(`\t\t\t${types[index].type}: ${data.toString()}`);
                });
            });
        });

        const tombstoneDeposit = await api.consts.contracts.tombstoneDeposit;
        console.log(`tombstone deposit min ${tombstoneDeposit}`);

        let constructorExecutionGas = 13500000000;
        let value = parseInt(tombstoneDeposit) + 100000000000000;
        console.log(`instantiating with value ${value}`);

        code.tx.new({gasLimit: constructorExecutionGas, salt: null, value: value}, OWNER_ADDR)
            .signAndSend(bob, ({ status, events }) => {
                if (status.isInBlock || status.isFinalized) {
                    events
                        // find/filter for failed events
                        .filter(({ event }) =>
                            api.events.system.ExtrinsicFailed.is(event)
                        )
                        // we know that data for system.ExtrinsicFailed is
                        // (DispatchError, DispatchInfo)
                        .forEach(({ event: { data: [error, info] } }) => {
                            if (error.isModule) {
                                // for module errors, we have the section indexed, lookup
                                const decoded = api.registry.findMetaError(error.asModule);
                                const { documentation, method, section } = decoded;

                                console.log(`${section}.${method}: ${documentation.join(' ')}`);
                            } else {
                                // Other, CannotLookup, BadOrigin, no extra info
                                console.log(error.toString());
                            }
                        });
                    events
                        .filter(({ event }) =>
                            api.events.contracts.CodeStored.is(event)
                        )
                        .forEach(({ event: { data: [code_hash] } }) => {
                            console.log(`code hash: ${code_hash}`);
                        });
                    events
                        .filter(({ event }) =>
                            api.events.contracts.Instantiated.is(event)
                        )
                        .forEach(({ event: { data: [deployer, contract] } }) => {
                            console.log(`contract address: ${contract}`);
                        });
                }
            })
    })
})

@jacogr
Copy link
Member

jacogr commented Mar 8, 2021

The current version of the contracts interface requires the utility module to allow compatibility with both substrate 2. and 3.x contracts. (It is only needed in the older 2.x Substrate, in the 3.x version the code only deploys alongside a contract)

@jacogr jacogr added the support label Mar 8, 2021
@jacogr jacogr closed this as completed Mar 15, 2021
@naps62
Copy link

naps62 commented Mar 21, 2021

@jacogr sorry, but what do you mean by "requires the utility module"? Is it something we need to somehow load? I can't find any documentation on this

@jacogr
Copy link
Member

jacogr commented Mar 21, 2021

@naps62
Copy link

naps62 commented Mar 22, 2021

ah, so this is something that needs to go on the substrate implementation itself. So I assume canvas-node (the test node I'm using) is the one that needs to fix this?

@ascjones
Copy link
Contributor

I don't know about this, but canvas-node is using the contracts pallet v3.0.0 so should work if calling instantiate_with_code which deploys the code and creates an instance as part of the same transaction.

@naps62
Copy link

naps62 commented Mar 22, 2021

To clarify, I bumped into the same issue described here yesterday
I also used an adapted version of the snippet @vminkov posted above, but led to the same error

Also tried to debug the wrapper in the browser using my project's code, and it seems api.tx.utility is always undefined. Since the instantiation code from api-contracts relies on that, it fails

Currently using:
@polkadot/api-contracts 4.1.1
canvas-node `0.1.0-4de4830-x86_64-linux-gnu

@jacogr
Copy link
Member

jacogr commented Mar 22, 2021

utility.batch is only used on contracts 2, where instantiate_with_code is not available, acting as a shim to get the contracts 3 upload-deploy behavior on top of contracts 2 (it is not used anywhere else in the contracts layer) -

https://github.com/polkadot-js/api/blob/master/packages/api-contract/src/base/Code.ts#L71

(Support for v2 will be dropped in the upcoming weeks completely, non-upgraded chains are just creating noise - generally I leave around a 3 month grace-period from release to allow upgrades instead of just trying to support everything indefinitely. Canvas-node itself was upgraded on 23 Feb)

@polkadot-js-bot
Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue if you think you have a related problem or query.

@polkadot-js polkadot-js locked as resolved and limited conversation to collaborators May 31, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

6 participants