inkdevhub / drink

De-chained Ready-to-play ink! playground
Apache License 2.0
69 stars 15 forks source link

Error loading external contract in standalone project #103

Closed 0xLucca closed 8 months ago

0xLucca commented 8 months ago

I have created a standalone Rust project that attempts to load and use a Flipper smart contract located in an external flipper.contract file, rather than bundling the contract within the crate itself. When trying to load the flipper.contract, the following error is thrown:

Failed to load contract: BundleLoadFailed("Failed to parse metadata from the contract file:\nError(\"missing field `staticBufferSize`\", line: 0, column: 0)")

The versions of the relevant tools I am using are:

Below is a snippet of my code for loading the contract:

use drink::{
    runtime::MinimalRuntime, 
    session::{Session, NO_ARGS, NO_ENDOWMENT, NO_SALT},
    ContractBundle,
};
use std::path::Path;

fn main() -> Result<(), Box<dyn std::error::Error>> {
  let mut session = Session::<MinimalRuntime>::new()?;

  let contract_path = Path::new("./flipper.contract");
  let contract = ContractBundle::load(contract_path)
    .expect("Failed to load contract");

  Ok(())  
}

The flipper.contract file has the following contents:

{
    "source": {
        "hash": "0xb5dda14042f7d7c89b4d6598013a2633de4343fba7024498c88f5c08c4fbf7a5",
        "language": "ink! 4.3.0",
        "compiler": "rustc 1.76.0-nightly",
        "wasm": "0x0061736d0100000001240760027f7f0060000060047f7f7f7f017f60037f7f7f006000017f60017f017f60017f00027406057365616c310b6765745f73746f726167650002057365616c301176616c75655f7472616e736665727265640000057365616c3005696e7075740000057365616c320b7365745f73746f726167650002057365616c300b7365616c5f72657475726e000303656e76066d656d6f727902010210030b0a000304050100060001010608017f01418080040b0711020463616c6c000d066465706c6f79000e0aa3090a2601017f230041106b22022400200220003a000f20012002410f6a41011006200241106a24000b6f01037f024002402000280208220320026a22042003490d00200420002802044b0d00200420036b2002470d01200028020020036a210541002103037f2002200346047f200505200320056a200120036a2d00003a0000200341016a21030c010b0b1a200020043602080f0b000b000b4d02017f027e230041206b2200240020004200370308200042003703002000411036021c20002000411c6a10012000290308210120002903002102200041206a2400410541042001200284501b0b4701017f4101410220002802042201047f2000200141016b36020420002000280200220041016a36020020002d00000520000b41ff017122004101461b410020001b410220011b0b12004180800441003b010041004102100c000b3c01027f027f200145044041808004210141010c010b410121024180800441013a000041818004210141020b2103200120023a000020002003100c000b960101047f230041106b2201240020014280800137020820014180800436020420014100360200200141046a200141041006024020012802082204200128020c2202490d00200128020421032001410036020c2001200420026b3602082001200220036a3602042000200141046a1005200128020c220020012802084b0d00200320022001280204200010031a200141106a24000f0b000b0d0020004180800420011004000b980301067f230041106b22002400024002400240100741ff01714105470d00200041808001360200418080042000100220002802002201418180014f0d0020014104490d02418380042d00002101418280042d00002102418180042d000021030240418080042d00002204412f470440200441e300470d04410121052003413a47200241a5014772200141d1004772450d010c040b200341860147200241db004772200141d90147720d030b2000428080013702042000418080043602002000410036020c20002000410c6a410410062000280204220320002802082201490d00200028020021022000200320016b220336020020022001200120026a22012000100020032000280200220249720d00200020023602042000200136020020001008220141ff01714102460d0020050d01230041106b220024002000418080043602044180800441003a00002000428080818010370208200141ff0171410047200041046a1005200028020c2200418180014f0440000b41002000100c000b000b200141ff017145100b41004100100a000b41014101100a000be30101057f230041106b2200240002400240100741ff01714105470d0020004180800136020c418080042000410c6a1002200028020c2201418180014f0d00024020014104490d002000418480043602042000200141046b360208418380042d00002101418280042d00002102418180042d00002103418080042d0000220441ed014704402004419b0147200341ae0147722002419d0147200141de004772720d01200041046a1008220041ff01714102460d012000100b1009000b200341cb00472002419d0147720d002001411b460d020b41014101100a000b000b4100100b1009000b",
        "build_info": {
            "build_mode": "Release",
            "cargo_contract_version": "3.2.0",
            "rust_toolchain": "nightly-aarch64-apple-darwin",
            "wasm_opt_settings": {
                "keep_debug_symbols": false,
                "optimization_passes": "Z"
            }
        }
    },
    "contract": {
        "name": "flipper",
        "version": "0.1.0",
        "authors": ["[your_name] <[your_email]>"]
    },
    "spec": {
        "constructors": [{
            "args": [{
                "label": "init_value",
                "type": {
                    "displayName": ["bool"],
                    "type": 0
                }
            }],
            "default": false,
            "docs": ["Constructor that initializes the `bool` value to the given `init_value`."],
            "label": "new",
            "payable": false,
            "returnType": {
                "displayName": ["ink_primitives", "ConstructorResult"],
                "type": 1
            },
            "selector": "0x9bae9d5e"
        }, {
            "args": [],
            "default": false,
            "docs": ["Constructor that initializes the `bool` value to `false`.", "", "Constructors can delegate to other constructors."],
            "label": "default",
            "payable": false,
            "returnType": {
                "displayName": ["ink_primitives", "ConstructorResult"],
                "type": 1
            },
            "selector": "0xed4b9d1b"
        }],
        "docs": [],
        "environment": {
            "accountId": {
                "displayName": ["AccountId"],
                "type": 5
            },
            "balance": {
                "displayName": ["Balance"],
                "type": 8
            },
            "blockNumber": {
                "displayName": ["BlockNumber"],
                "type": 11
            },
            "chainExtension": {
                "displayName": ["ChainExtension"],
                "type": 12
            },
            "hash": {
                "displayName": ["Hash"],
                "type": 9
            },
            "maxEventTopics": 4,
            "timestamp": {
                "displayName": ["Timestamp"],
                "type": 10
            }
        },
        "events": [],
        "lang_error": {
            "displayName": ["ink", "LangError"],
            "type": 3
        },
        "messages": [{
            "args": [],
            "default": false,
            "docs": [" A message that can be called on instantiated contracts.", " This one flips the value of the stored `bool` from `true`", " to `false` and vice versa."],
            "label": "flip",
            "mutates": true,
            "payable": false,
            "returnType": {
                "displayName": ["ink", "MessageResult"],
                "type": 1
            },
            "selector": "0x633aa551"
        }, {
            "args": [],
            "default": false,
            "docs": [" Simply returns the current value of our `bool`."],
            "label": "get",
            "mutates": false,
            "payable": false,
            "returnType": {
                "displayName": ["ink", "MessageResult"],
                "type": 4
            },
            "selector": "0x2f865bd9"
        }]
    },
    "storage": {
        "root": {
            "layout": {
                "struct": {
                    "fields": [{
                        "layout": {
                            "leaf": {
                                "key": "0x00000000",
                                "ty": 0
                            }
                        },
                        "name": "value"
                    }],
                    "name": "Flipper"
                }
            },
            "root_key": "0x00000000"
        }
    },
    "types": [{
        "id": 0,
        "type": {
            "def": {
                "primitive": "bool"
            }
        }
    }, {
        "id": 1,
        "type": {
            "def": {
                "variant": {
                    "variants": [{
                        "fields": [{
                            "type": 2
                        }],
                        "index": 0,
                        "name": "Ok"
                    }, {
                        "fields": [{
                            "type": 3
                        }],
                        "index": 1,
                        "name": "Err"
                    }]
                }
            },
            "params": [{
                "name": "T",
                "type": 2
            }, {
                "name": "E",
                "type": 3
            }],
            "path": ["Result"]
        }
    }, {
        "id": 2,
        "type": {
            "def": {
                "tuple": []
            }
        }
    }, {
        "id": 3,
        "type": {
            "def": {
                "variant": {
                    "variants": [{
                        "index": 1,
                        "name": "CouldNotReadInput"
                    }]
                }
            },
            "path": ["ink_primitives", "LangError"]
        }
    }, {
        "id": 4,
        "type": {
            "def": {
                "variant": {
                    "variants": [{
                        "fields": [{
                            "type": 0
                        }],
                        "index": 0,
                        "name": "Ok"
                    }, {
                        "fields": [{
                            "type": 3
                        }],
                        "index": 1,
                        "name": "Err"
                    }]
                }
            },
            "params": [{
                "name": "T",
                "type": 0
            }, {
                "name": "E",
                "type": 3
            }],
            "path": ["Result"]
        }
    }, {
        "id": 5,
        "type": {
            "def": {
                "composite": {
                    "fields": [{
                        "type": 6,
                        "typeName": "[u8; 32]"
                    }]
                }
            },
            "path": ["ink_primitives", "types", "AccountId"]
        }
    }, {
        "id": 6,
        "type": {
            "def": {
                "array": {
                    "len": 32,
                    "type": 7
                }
            }
        }
    }, {
        "id": 7,
        "type": {
            "def": {
                "primitive": "u8"
            }
        }
    }, {
        "id": 8,
        "type": {
            "def": {
                "primitive": "u128"
            }
        }
    }, {
        "id": 9,
        "type": {
            "def": {
                "composite": {
                    "fields": [{
                        "type": 6,
                        "typeName": "[u8; 32]"
                    }]
                }
            },
            "path": ["ink_primitives", "types", "Hash"]
        }
    }, {
        "id": 10,
        "type": {
            "def": {
                "primitive": "u64"
            }
        }
    }, {
        "id": 11,
        "type": {
            "def": {
                "primitive": "u32"
            }
        }
    }, {
        "id": 12,
        "type": {
            "def": {
                "variant": {}
            },
            "path": ["ink_env", "types", "NoChainExtension"]
        }
    }],
    "version": "4"
}

I have done some more debugging and found that trying to load the contract directly using the drink transcoder also results in the same error. So the issue seems to be around how the contract file is getting decoded, rather than just the way I am trying to load it in my project.

Let me know if any other details would be helpful!

pmikolajczyk41 commented 8 months ago

@0xLucca I reproduced the error. The problem is with too old cargo contract tool. The recent version (4.x) adds additional information to the bundle (including the missing staticBufferSize field).

When I rerun the experiment with newest cargo contract, your main works well.

For updating cargo contract I use:

cargo install cargo-contract --force --locked --version 4.0.0-rc.1
0xLucca commented 8 months ago

Hey @pmikolajczyk41!

Thanks for looking into this further! You were correct - upgrading to the latest cargo-contract (v4.x) resolved the issues I was seeing when trying to load my external flipper.contract file.

One followup question - many existing contract bundles created with older cargo-contract versions will be missing some of this newer metadata added in v4.x. Is there a recommended way to handle loading/decoding contracts with these older bundle formats?

pmikolajczyk41 commented 8 months ago

if you are asking about handling these bundles with drink, then I guess the easiest way is to use some older version of drink (as far as I remember versions around 0.8.x should work fine with ink 4)

however, if feasible, I would recompile the contract with newer cargo-contract