@@ -60,6 +60,7 @@ This repo is designed to train Rust developers on intermediate and advanced Rust
6060 - [ Contracts] ( #contracts )
6161 - [ WIT] ( #wit )
6262 - [ Sample Contract - Erc20] ( #sample-contract---erc20 )
63+ - [ Invoking a Contract Function] ( #invoking-a-contract-function )
6364 - [ Web3] ( #web3 )
6465 - [ Sample Usage] ( #sample-usage )
6566 - [ Types] ( #types )
@@ -735,8 +736,17 @@ fn process_transaction<'a>(
735736 contract_address = self . accounts. add_contract_account (& from , data ). ok ();
736737 Ok (())
737738 }
738- TransactionKind :: ContractExecution (_from , _to , _data ) => {
739- unimplemented! ()
739+ TransactionKind :: ContractExecution (_from , to , data ) => {
740+ let code = self
741+ . accounts
742+ . get_account (& to )?
743+ . code_hash
744+ . ok_or_else (|| ChainError :: NotAContractAccount (to . to_string ()))? ;
745+ let (function , params ): (& str , Vec <& str >) = bincode :: deserialize (& data )? ;
746+
747+ // call the function in the contract
748+ runtime :: contract :: call_function (& code , function , & params )
749+ . map_err (| e | ChainError :: RuntimeError (to . to_string (), e . to_string ()))
740750 }
741751 }? ;
742752
@@ -777,9 +787,43 @@ pub fn add_contract_account(&mut self, key: &Account, data: Bytes) -> Result<Acc
777787
778788Code received gets added to the ` to ` account's ` code_hash ` attribute.
779789
780- _ TODO: document processing a contract execution _
790+ Contract execution involves calling a function in the contract in a WASM virtual machine (Wasmtime). This sandboxing isolates contract execution from the rest of the blockchain. We first must get the executable code from account storage:
781791
782- After the transaction is processed, the ` from ` account's ` nonce ` is updated. A ` transaction receipt ` is created and returned from the function.
792+ ``` rust
793+ let code = self
794+ . accounts
795+ . get_account (& to )?
796+ . code_hash
797+ . ok_or_else (|| ChainError :: NotAContractAccount (to . to_string ()))? ;
798+ ```
799+
800+ Now we just extract the function name and the function parameters from the ` data ` node in the transaction request:
801+
802+ ``` rust
803+ let (function , params ): (& str , Vec <& str >) = bincode :: deserialize (& data )? ;
804+ ```
805+
806+ For example, let's say we want to invoke the ` construct ` function. The function signature of ` construct ` contract function is:
807+
808+ ``` rust
809+ fn construct (name : String , symbol : String ) {}
810+ ```
811+
812+ We serialize the parameter types and values:
813+
814+
815+ ``` rust
816+ // ["Param 1 Type", "Param 1 Value", "Param 2 Type", "Param 2 Value"]
817+ let params = [" String" , " Rust Coin" , " String" , " RustCoin" ];
818+ ```
819+
820+ We can now invoke the ` construct ` function:
821+
822+ ``` rust
823+ runtime :: contract :: call_function (& code , " construct" , & params )? ;
824+ ```
825+
826+ After we've handled one of the 3 transaction types, the ` from ` account's ` nonce ` is updated. A ` transaction receipt ` is created and returned from the function.
783827
784828## Organization
785829
@@ -849,7 +893,7 @@ use wit_bindgen_guest_rust::*;
849893
850894wit_bindgen_guest_rust :: generate! ({path : " ../erc20/erc20.wit" , world : " erc20" });
851895
852- struct Erc20 {}
896+ struct Erc20 ;
853897
854898export_contract! (Erc20 );
855899
@@ -868,6 +912,19 @@ impl erc20::Erc20 for Erc20 {
868912}
869913```
870914
915+ #### Invoking a Contract Function
916+
917+ This code can convert the textual representation of a contract function call to a function call within the wasmtime runtime.
918+ Parameters are listed in pairs of parameter type and paramater value.
919+
920+ ``` rust
921+ let bytes = include_bytes! (" ./../../target/wasm32-unknown-unknown/release/erc20_wit.wasm" );
922+ let function_name = " construct" ;
923+ let params = & [" String" , " Rust Coin" , " String" , " RustCoin" ];
924+
925+ call_function (bytes , function_name , params )? ;
926+ ```
927+
871928### Web3
872929
873930The [ web3] ( web3 ) crate is a naive implementation of a Web3 interface.
@@ -887,7 +944,7 @@ let block_number = web3.get_block_number().await?;
887944let block = web3 . get_block (* block_number ). await ? ;
888945
889946let contract =
890- include_bytes! (" ./../../contracts/artifacts/contracts/ERC20.sol/RustCoinToken.json " ). to_vec ();
947+ include_bytes! (" ./../../target/wasm32-unknown-unknown/release/erc20_wit.wasm " ). to_vec ();
891948let tx_hash = web3 . deploy (all_accounts [0 ], & contract ). await ? ;
892949let receipt = web3 . transaction_receipt (tx_hash ). await ? ;
893950let code = web3 . code (receipt . contract_address. unwrap (), None ). await ? ;
0 commit comments