Extrinsic failed when invoke HashMap/BTreeMap insert() in ink! contract via Polkadot JS api

妖精的绣舞 提交于 2020-06-28 09:22:34

问题


I got an issue when invoke a contract call from Polkadot JS api.

If the function include HashMap insert() or BTreeMap insert() in contract, when call it via api, I'll get:

{"ApplyExtrinsic":1}
[ An extrinsic failed.]
{"index":"0x0001","data":[{"Other":null},{"weight":10000000000,"class":"Normal","paysFee":"Yes"}]}

Event won't be triggered correctly. But if I use HashMap/ BTreeMap get() or contains_key(), I can get event data correctly.

Here's my contract code in lib.rs:

/* 
    Using the standard library if we run the tests module, 
    or if we use a std feature flag within our code. 
    Otherwise the contract will always compile with no_std.
*/
#![cfg_attr(not(feature = "std"), no_std)]

extern crate hex;

use ink_lang as ink;

#[ink::contract(version = "0.1.0")]
mod roleContract {
    #[cfg(not(feature = "ink-as-dependency"))]
    use ink_core::storage;
    use ink_core::storage::BTreeMap;

    /// Defines the storage of your contract.
    /// Add new fields to the below struct in order
    /// to add new static storage fields to your contract.
    #[ink(storage)]
    struct RoleContract {
        /// Stores a single `bool` value on the storage.
        test_hashmap: storage::hash_map::HashMap<AccountId, u64>,
        test_btreemap: storage::BTreeMap<AccountId, u64>,
    }

    #[ink(event)]
    struct TestEvent {
        #[ink(topic)]
        isOk: u32,
    }

    impl RoleContract {
        /// Constructor that initializes the caller as roleType = 1 (System)
        #[ink(constructor)]
        fn newRoleContract(&mut self) {}

        /// Add caller type
        #[ink(message)]
    fn setType(&mut self) {
        let bytes: [u8; 32] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let acc = AccountId::from(bytes);
        let default_value:u64 = 1;
        // self.test_hashmap.insert(acc, default_value);
        self.test_btreemap.insert(acc, default_value);

        self.env()
            .emit_event(
                TestEvent {
                    isOk: 1,
                }
            );
        }
    }
}

And here's the js file for api call:

async function main() {
    const provider = new WsProvider('ws://127.0.0.1:9944');
    const api = await ApiPromise.create({ provider: provider, types: {
        "Address": "AccountId",
        "LookupSource": "AccountId"
    } });

    const BOB="5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty";
    const ALICE = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY";

    const keyring = new Keyring({ type: 'sr25519' });
    const alice=keyring.addFromUri("//Alice");
    
    const setTypeSelector="0xEE03889D"; //from abi

    const contractAddress = "0x33b757c837aaf6946de25ca35046fadb62e99848c7fe1d106404cb02a298bcf7";

    const callTx=api.tx.contracts.call(contractAddress, 0, 10000000000, setTypeSelector);

    console.log(callTx.toString());
    console.log(callTx.toHuman());
    console.log(callTx.toRawType());

    await callTx.signAndSend(alice, ({events=[], status}) => {
        if(status.isInBlock) {
        console.log("callTx (set caller's type) is in block");
        events.forEach(({event, phase}) => {
            console.log(event.toHuman());
            console.log(phase.toString());
            console.log(event.meta.documentation.toString());
            console.log(event.toString());
            if(event.section=="contracts" && event.method=="ContractExecution") {
            console.log("contract returned from", event.data[0].toHex(), "with pub key value", event.data[1]);
            }
        });

        } else {
        console.log('\n', "callTx (set caller's type) waiting to be in block");
        }
    });
}

Anyone knows what the issue is?

来源:https://stackoverflow.com/questions/62601759/extrinsic-failed-when-invoke-hashmap-btreemap-insert-in-ink-contract-via-polk

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!