Compile and Deploy smart contract in local testnet

Hi!

Everything is at a very early stage. At the moment, as the documentation says:

Custom Move programs are not supported in the initial testnet release, but these features are available for you to try out locally

For testing purposes, you can copy your file to test directory:
libra/language/functional_tests/tests/testsuite/modules

and run
cargo test -p functional_tests modules

You can also try to use a compiler (instruction at the link below)

4 Likes

Thanks For Answering.
So it will only compile not deploy contact.

2 Likes

Hi @YuvrajUpadhyay, we recently deployed an update to the client which allows testing execution of programs. @runtianz to provide more details

3 Likes

@runtianz can you provide some guidance for deploying smart contact?

1 Like

Really?

Is there any documentation? A very short howto for running an own move smart contract?

1 Like

Sure! To deploy a smart contract, there will be three steps:

  1. Use compiler binary to compile a move script into a TransactionProgram. Example command:
    ./compiler -o ~/out.program peer_to_peer_transfer.mvir
  2. Use transaction_builder binary to build a transaction given such program. Example:
    ./transaction_builder 4efec659b58309c077ffe53689dfa3d37dc45b3678751b03a3b2b0d2c69f2271 0 ~/out.program out.txn --args 0x70111e54a7190c1124325a322d608b5e56e5e4634bab5b3879bd6422364c6525 100
    The first 4efec... is the sender address, 0x70111... is the recipient address, 100 is the transaction amount.
  3. Send this transaction via the client CLI:
    submitb 4efec659b58309c077ffe53689dfa3d37dc45b3678751b03a3b2b0d2c69f2271 out.txn
    The 4efc... is the signer of this transaction.

A detailed blog post on how to deploy your smart contract will follow shortly.

10 Likes

Thanks for guidance.

Will wait for your blog.

1 Like

@runtianz Thanks for sharing steps to deploy a smart contract. We are waiting for detailed blog.

2 Likes

Hi,

I will test that. But how can u run something against this contract. Is there a way to interact with it? Call methods, see results?

1 Like

Awesome, I have been waiting for this release. Thanks

1 Like

@runtianz Hi Runtian, is there something similar to the ABI in Solidity, so that we can interact with the deployed contract?

Thanks

1 Like

/expecting

1 Like

FYI

i’ve tested

// Simple peer-peer payment example.

// Use LibraAccount module published on the blockchain at account address
// 0x0...0 (with 64 zeroes). 0x0 is shorthand that the IR pads out to
// 256 bits (64 digits) by adding leading zeroes.
import 0x0.toto.LibraAccount;
import 0x0.LibraCoin;
main(payee: address, amount: u64) {
  // The bytecode (and consequently, the IR) has typed locals.  The scope of
  // each local is the entire procedure. All local variable declarations must
  // be at the beginning of the procedure. Declaration and initialization of
  // variables are separate operations, but the bytecode verifier will prevent
  // any attempt to use an uninitialized variable.
  let coin: R#LibraCoin.T;
  // The R# part of the type above is one of two *kind annotation* R# and V#
  // (shorthand for "Resource" and "unrestricted Value"). These annotations
  // must match the kind of the type declaration (e.g., does the LibraCoin
  // module declare `resource T` or `struct T`?).

  // Acquire a LibraCoin.T resource with value `amount` from the sender's
  // account.  This will fail if the sender's balance is less than `amount`.
  coin = LibraAccount.withdraw_from_sender(move(amount));
  // Move the LibraCoin.T resource into the account of `payee`. If there is no
  // account at the address `payee`, this step will fail
  LibraAccount.deposit(move(payee), move(coin));

  // Every procedure must end in a `return`. The IR compiler is very literal:
  // it directly translates the source it is given. It will not do fancy
  // things like inserting missing `return`s.
  return;
}

wich compiles nicely using https://libraide.com/

but when testing with $ cargo test -p functional_tests modules i got

ubuntu:~/environment/libra (master) $ cargo test -p functional_tests modules
    Finished dev [unoptimized + debuginfo] target(s) in 0.25s
     Running target/debug/deps/functional_tests-7422322bc9e10e6c

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 23 filtered out

     Running target/debug/deps/testsuite-19b7cacfa2561aae

running 17 tests
test functional_tests::modules/access_private_function.mvir ... ok
test functional_tests::modules/access_public_function.mvir ... ok
test functional_tests::modules/duplicate_function_name.mvir ... ok
test functional_tests::modules/duplicate_struct_name.mvir ... ok
test functional_tests::modules/all_fields_accessible.mvir ... ok
test functional_tests::modules/function_in_struct.mvir ... ok
test functional_tests::modules/get_resource_internal.mvir ... ok
test functional_tests::modules/get_resource_internal_bypass.mvir ... ok
test functional_tests::modules/lucastest.mvir ... FAILED
test functional_tests::modules/has_resource_internal.mvir ... ok
test functional_tests::modules/modules_not_a_type.mvir ... ok
test functional_tests::modules/module_struct_shared_name.mvir ... ok
test functional_tests::modules/mutual_recursive_struct.mvir ... ok
test functional_tests::modules/publish_resource_internal.mvir ... ok
test functional_tests::publish/publish_duplicate_modules.mvir ... ok
test functional_tests::publish/publish_two_modules.mvir ... ok
test functional_tests::publish/use_modules_published.mvir ... ok

failures:

---- functional_tests::modules/lucastest.mvir stdout ----
EvaluationResult {
    outputs: [
        Transaction,
        Stage(
            Parser,
        ),
        Output(
            "Program { modules: [], script: Script { imports: [ImportDefinition { ident: Qualified(QualifiedModuleIdent { name: ModuleName(\"LibraAccount\"), address: 0000000000000000000000000000000000000000000000000000000000000000 }), alias: ModuleName(\"LibraAccount\") }, ImportDefinition { ident: Qualified(QualifiedModuleIdent { name: ModuleName(\"LibraCoin\"), address: 0000000000000000000000000000000000000000000000000000000000000000 }), alias: ModuleName(\"LibraCoin\") }], main: Function { visibility: Public, signature: FunctionSignature { formals: [(Var(\"payee\"), Normal(Value, Address)), (Var(\"amount\"), Normal(Value, U64))], return_type: [] }, annotations: [], body: Move { locals: [(Spanned { span: Span { start: ByteIndex(89), end: ByteIndex(93) }, value: Var(\"coin\") }, Normal(Resource, Struct(StructType { module: ModuleName(\"LibraCoin\"), name: StructName(\"T\") })))], code: Block { stmts: [CommandStatement(Spanned { span: Span { start: ByteIndex(112), end: ByteIndex(166) }, value: Assign([Spanned { span: Span { start: ByteIndex(112), end: ByteIndex(116) }, value: Var(\"coin\") }], Spanned { span: Span { start: ByteIndex(119), end: ByteIndex(166) }, value: FunctionCall(ModuleFunctionCall { module: ModuleName(\"LibraAccount\"), name: FunctionName(\"withdraw_from_sender\") }, Spanned { span: Span { start: ByteIndex(152), end: ByteIndex(166) }, value: ExprList([Spanned { span: Span { start: ByteIndex(153), end: ByteIndex(165) }, value: Move(Spanned { span: Span { start: ByteIndex(158), end: ByteIndex(164) }, value: Var(\"amount\") }) }]) }) }) }), CommandStatement(Spanned { span: Span { start: ByteIndex(170), end: ByteIndex(215) }, value: Exp(Spanned { span: Span { start: ByteIndex(170), end: ByteIndex(215) }, value: FunctionCall(ModuleFunctionCall { module: ModuleName(\"LibraAccount\"), name: FunctionName(\"deposit\") }, Spanned { span: Span { start: ByteIndex(190), end: ByteIndex(215) }, value: ExprList([Spanned { span: Span { start: ByteIndex(191), end: ByteIndex(202) }, value: Move(Spanned { span: Span { start: ByteIndex(196), end: ByteIndex(201) }, value: Var(\"payee\") }) }, Spanned { span: Span { start: ByteIndex(204), end: ByteIndex(214) }, value: Move(Spanned { span: Span { start: ByteIndex(209), end: ByteIndex(213) }, value: Var(\"coin\") }) }]) }) }) }), CommandStatement(Spanned { span: Span { start: ByteIndex(219), end: ByteIndex(225) }, value: Return(Spanned { span: Span { start: ByteIndex(0), end: ByteIndex(0) }, value: ExprList([]) }) })] } } } } }",
        ),
        Stage(
            Compiler,
        ),
        Output(
            "CompiledProgram { modules: [], script: CompiledScript(CompiledScriptMut { module_handles: [ModuleHandle { address: AddressPoolIndex(0), name: StringPoolIndex(0) }, ModuleHandle { address: AddressPoolIndex(1), name: StringPoolIndex(1) }, ModuleHandle { address: AddressPoolIndex(1), name: StringPoolIndex(2) }], struct_handles: [StructHandle { module: ModuleHandleIndex(2), name: StringPoolIndex(4), kind: Resource, kind_constraints: [] }], function_handles: [FunctionHandle { module: ModuleHandleIndex(0), name: StringPoolIndex(3), signature: FunctionSignatureIndex(0) }, FunctionHandle { module: ModuleHandleIndex(1), name: StringPoolIndex(5), signature: FunctionSignatureIndex(1) }, FunctionHandle { module: ModuleHandleIndex(1), name: StringPoolIndex(6), signature: FunctionSignatureIndex(2) }], type_signatures: [], function_signatures: [FunctionSignature { return_types: [], arg_types: [Address, U64], kind_constraints: [] }, FunctionSignature { return_types: [Struct(StructHandleIndex(0), [])], arg_types: [U64], kind_constraints: [] }, FunctionSignature { return_types: [], arg_types: [Address, Struct(StructHandleIndex(0), [])], kind_constraints: [] }], locals_signatures: [LocalsSignature([]), LocalsSignature([Address, U64, Struct(StructHandleIndex(0), [])])], string_pool: [\"<SELF>\", \"LibraAccount\", \"LibraCoin\", \"main\", \"T\", \"withdraw_from_sender\", \"deposit\"], byte_array_pool: [], address_pool: [a6286842bef987cc368aef0982ece080eba1a07edef2deb5036a039e26287940, 0000000000000000000000000000000000000000000000000000000000000000], main: FunctionDefinition { function: FunctionHandleIndex(0), flags: 1, code: CodeUnit { max_stack_size: 2, locals: LocalsSignatureIndex(1), code: [MoveLoc(1), Call(1, LocalsSignatureIndex(0)), StLoc(2), MoveLoc(0), MoveLoc(2), Call(2, LocalsSignatureIndex(0)), Ret] } } }) }",
        ),
        Stage(
            Verifier,
        ),
        Output(
            "",
        ),
        Stage(
            Serializer,
        ),
        Stage(
            Runtime,
        ),
        Error(
            "DiscardedTransaction(TransactionOutput { write_set: WriteSet(WriteSetMut { write_set: [] }), events: [], gas_used: 0, status: Discard(Verification([Script(TypeMismatch(\"Actual Type Mismatch\"))])) })",
        ),
    ],
    status: Failure,
}
Error: Other("program failed at transaction 1, stage Runtime, no directives found, assuming failure")
thread 'functional_tests::modules/lucastest.mvir' panicked at 'assertion failed: `(left == right)`
  left: `1`,
 right: `0`: the test returned a termination value with a non-zero status code (1) which indicates a failure', /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/datatest-0.3.5/src/runner.rs:265:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.


failures:
    functional_tests::modules/lucastest.mvir

test result: FAILED. 16 passed; 1 failed; 0 ignored; 0 measured; 262 filtered out

thread 'main' panicked at 'Some tests failed', /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/datatest-0.3.5/src/runner.rs:257:22
error: test failed, to rerun pass '-p functional_tests --test testsuite'

=> here is the compiled version by https://libraide.com/

CompiledProgram: {
Modules: [
],
Script: CompiledScript: {
Main:
	public 0x0.<SELF>.main(Address, Integer): ()
		locals(0): Address, Integer, resource T@0x0.LibraCoin,
		MoveLoc(1)
		Call(0x0.LibraAccount.withdraw_from_sender(Integer): (resource T@0x0.LibraCoin))
		StLoc(2)
		MoveLoc(0)
		MoveLoc(2)
		Call(0x0.LibraAccount.deposit(Address, resource T@0x0.LibraCoin): ())
		Ret
Struct Handles: [
	resource T@0x0.LibraCoin,]
Module Handles: [
	0x0.<SELF>,
	0x0.LibraAccount,
	0x0.LibraCoin,]
Function Handles: [
	0x0.<SELF>.main(Address, Integer): (),
	0x0.LibraAccount.withdraw_from_sender(Integer): (resource T@0x0.LibraCoin),
	0x0.LibraAccount.deposit(Address, resource T@0x0.LibraCoin): (),]
Type Signatures: []
Function Signatures: [
	(Address, Integer): (),
	(Integer): (resource T@0x0.LibraCoin),
	(Address, resource T@0x0.LibraCoin): (),]
Locals Signatures: [
	Address, Integer, resource T@0x0.LibraCoin,]
Strings: [
	<SELF>,
	LibraAccount,
	LibraCoin,
	main,
	T,
	withdraw_from_sender,
	deposit,]
ByteArrays: []
Addresses: [
	0x0,]
}

}

edit : not working neither testing the compiled .mvir file into testsuit folder

1 Like

This isn’t a compiled version of the contract, this is a display of the contract for convenience

compiling contract Example: {“code”:[76,73,66,82,65,… “args”:,“modules”:[[76,73,66 …

1 Like

Hi @lucas

I’ve got the same result when testing your code with $ cargo ....
I’ve noticed that testing only script always failed. Only testing modules gives correct result. In the end we put file to test into modules directory…
The code compiles correctly using cargo run -p compiler ./test/sample.mvir

 cargo run -p compiler ./test/sample.mvir
   Compiling types v0.1.0 (/Users/paulina/projects/libra/types)
   Compiling ir_to_bytecode_syntax v0.1.0 (/Users/paulina/projects/libra/language/compiler/ir_to_bytecode/syntax)
   Compiling vm v0.1.0 (/Users/paulina/projects/libra/language/vm)
   Compiling bytecode_verifier v0.1.0 (/Users/paulina/projects/libra/language/bytecode_verifier)
   Compiling ir_to_bytecode v0.1.0 (/Users/paulina/projects/libra/language/compiler/ir_to_bytecode)
   Compiling stdlib v0.1.0 (/Users/paulina/projects/libra/language/stdlib)
   Compiling compiler v0.1.0 (/Users/paulina/projects/libra/language/compiler)
    Finished dev [unoptimized + debuginfo] target(s) in 17.16s
     Running `target/debug/compiler ./test/sample.mvir`
CompiledProgram: {
Modules: [
],
Script: CompiledScript: {
Main:
	public 0x0.<SELF>.main(Address, Integer): ()
		locals(0): Address, Integer, resource T@0x0.LibraCoin,
		MoveLoc(1)
		Call(0x0.LibraAccount.withdraw_from_sender(Integer): (resource T@0x0.LibraCoin))
		StLoc(2)
		MoveLoc(0)
		MoveLoc(2)
		Call(0x0.LibraAccount.deposit(Address, resource T@0x0.LibraCoin): ())
		Ret
Struct Handles: [
	resource T@0x0.LibraCoin,]
Module Handles: [
	0x0.<SELF>,
	0x0.LibraAccount,
	0x0.LibraCoin,]
Function Handles: [
	0x0.<SELF>.main(Address, Integer): (),
	0x0.LibraAccount.withdraw_from_sender(Integer): (resource T@0x0.LibraCoin),
	0x0.LibraAccount.deposit(Address, resource T@0x0.LibraCoin): (),]
Type Signatures: []
Function Signatures: [
	(Address, Integer): (),
	(Integer): (resource T@0x0.LibraCoin),
	(Address, resource T@0x0.LibraCoin): (),]
Locals Signatures: [
	Address, Integer, resource T@0x0.LibraCoin,]
Strings: [
	<SELF>,
	LibraAccount,
	LibraCoin,
	main,
	T,
	withdraw_from_sender,
	deposit,]
ByteArrays: []
Addresses: [
	0x0,]
}

}

PS. There is a typo in your pasted code import 0x0.toto.LibraAccount

2 Likes

Hi, based on the answer of @runtianz I’ve prepared post showing how to compile and deploy that transaction script to the local testnet.

2 Likes

Hi @Paulinareally enjoyed reading your article! Will this work for any type of move script (like token implementation) or just transactional scripts?

1 Like

Hi @alonshavit, it works for transaction scripts but there is still a problem to deploy Move modules. We are using transaction_builder and i did’t find a way to use it for modules
At GitHub we can read that the the CLI tools don’t currently have a way craft a module deployment transaction

1 Like

Thank you so much @Paulina for the elaborated answer! i guess we will have to wait a bit… this kind of information is very valuable for our community at www.libracamp.com and i would love to see you take part in it!

3 Likes

submit/submitb commands not working anymore.

1 Like