From f7573bb942b956097e0d1f06a61770ee1f8c60f0 Mon Sep 17 00:00:00 2001
From: 0xPause <zhouyafei125@gmail.com>
Date: Mon, 16 Oct 2023 23:39:08 +0800
Subject: [PATCH] Auto sort modules by dependency order and review native
 function errors (#971)

* auto sort modules by dependency order

* auto sort modules

* unify native function errors

* fix verification error and update error code
---
 Cargo.lock                                    |  1 +
 .../tests/cases/table/test_destroy.exp        |  2 +-
 crates/rooch-framework/doc/bcs.md             | 16 ++++++
 crates/rooch-framework/doc/bitcoin_address.md | 18 +++---
 crates/rooch-framework/doc/decoding.md        | 16 ++++++
 .../doc/ecdsa_k1_recoverable.md               | 10 ++++
 crates/rooch-framework/doc/encoding.md        | 46 ++++++++++++++++
 crates/rooch-framework/sources/bcs.move       |  3 +
 .../sources/crypto/decoding.move              |  4 ++
 .../sources/crypto/ecdsa_k1.move              |  5 +-
 .../sources/crypto/ecdsa_k1_recoverable.move  | 11 ++--
 .../sources/crypto/encoding.move              | 13 +++++
 .../sources/crypto/schnorr.move               |  4 +-
 .../src/natives/gas_parameter/move_module.rs  |  4 +-
 .../src/natives/rooch_framework/bcs.rs        | 12 ++--
 .../rooch_framework/crypto/decoding.rs        | 14 ++---
 .../rooch_framework/crypto/ecdsa_k1.rs        | 12 ++--
 .../crypto/ecdsa_k1_recoverable.rs            | 41 +++++++++-----
 .../natives/rooch_framework/crypto/ed25519.rs |  4 +-
 .../rooch_framework/crypto/encoding.rs        | 38 ++++++-------
 .../natives/rooch_framework/crypto/schnorr.rs | 12 ++--
 examples/publish_modules/sources/publish.move |  2 +-
 moveos/moveos-stdlib-builder/Cargo.toml       |  1 -
 .../src/dependency_order.rs                   |  2 +-
 moveos/moveos-stdlib/Cargo.toml               |  3 +-
 .../moveos-stdlib/doc/account_storage.md      |  7 +--
 moveos/moveos-stdlib/moveos-stdlib/doc/bcs.md | 16 ++++++
 .../moveos-stdlib/doc/move_module.md          | 55 ++++++++++++++++---
 .../moveos-stdlib/doc/raw_table.md            | 12 +++-
 .../sources/account_storage.move              | 20 +++++--
 .../moveos-stdlib/sources/bcs.move            |  3 +
 .../moveos-stdlib/sources/move_module.move    | 29 ++++++----
 .../moveos-stdlib/sources/raw_table.move      |  4 +-
 .../src/natives/moveos_stdlib/bcs.rs          | 12 ++--
 .../src/natives/moveos_stdlib/move_module.rs  | 53 ++++++++++++------
 .../natives/moveos_stdlib/raw_table/mod.rs    |  1 +
 36 files changed, 372 insertions(+), 134 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 8a72c27501..80c4124142 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5082,6 +5082,7 @@ dependencies = [
  "move-vm-runtime",
  "move-vm-test-utils",
  "move-vm-types",
+ "moveos-stdlib-builder",
  "moveos-types",
  "moveos-verifier",
  "once_cell",
diff --git a/crates/rooch-framework-tests/tests/cases/table/test_destroy.exp b/crates/rooch-framework-tests/tests/cases/table/test_destroy.exp
index 55844b167d..c3d4b9613e 100644
--- a/crates/rooch-framework-tests/tests/cases/table/test_destroy.exp
+++ b/crates/rooch-framework-tests/tests/cases/table/test_destroy.exp
@@ -13,7 +13,7 @@ task 4 'run'. lines 109-124:
 status EXECUTED
 
 task 5 'run'. lines 125-137:
-status ABORTED with code 3 in 0000000000000000000000000000000000000000000000000000000000000002::raw_table
+status ABORTED with code 4 in 0000000000000000000000000000000000000000000000000000000000000002::raw_table
 
 task 6 'run'. lines 138-151:
 status EXECUTED
diff --git a/crates/rooch-framework/doc/bcs.md b/crates/rooch-framework/doc/bcs.md
index fb58bd6ca9..2784f4ca8a 100644
--- a/crates/rooch-framework/doc/bcs.md
+++ b/crates/rooch-framework/doc/bcs.md
@@ -10,6 +10,7 @@ function because this can violate implicit struct invariants, therefore only pri
 a general conversion back-and-force is needed, consider the <code>moveos_std::Any</code> type which preserves invariants.
 
 
+-  [Constants](#@Constants_0)
 -  [Function `to_bytes`](#0x3_bcs_to_bytes)
 -  [Function `to_bool`](#0x3_bcs_to_bool)
 -  [Function `to_u8`](#0x3_bcs_to_u8)
@@ -24,6 +25,21 @@ a general conversion back-and-force is needed, consider the <code>moveos_std::An
 
 
 
+<a name="@Constants_0"></a>
+
+## Constants
+
+
+<a name="0x3_bcs_ErrorTypeNotMatch"></a>
+
+The request Move type is not match with input Move type.
+
+
+<pre><code><b>const</b> <a href="bcs.md#0x3_bcs_ErrorTypeNotMatch">ErrorTypeNotMatch</a>: u64 = 1;
+</code></pre>
+
+
+
 <a name="0x3_bcs_to_bytes"></a>
 
 ## Function `to_bytes`
diff --git a/crates/rooch-framework/doc/bitcoin_address.md b/crates/rooch-framework/doc/bitcoin_address.md
index 8beb1afcc5..fcf77dc138 100644
--- a/crates/rooch-framework/doc/bitcoin_address.md
+++ b/crates/rooch-framework/doc/bitcoin_address.md
@@ -56,6 +56,15 @@
 ## Constants
 
 
+<a name="0x3_bitcoin_address_ErrorInvalidScriptVersion"></a>
+
+
+
+<pre><code><b>const</b> <a href="bitcoin_address.md#0x3_bitcoin_address_ErrorInvalidScriptVersion">ErrorInvalidScriptVersion</a>: u64 = 2;
+</code></pre>
+
+
+
 <a name="0x3_bitcoin_address_BECH32_ADDR_LENGTH"></a>
 
 Bech32 addresses including P2WPKH and P2WSH are 42 characters
@@ -102,15 +111,6 @@ Bech32 addresses including P2WPKH and P2WSH are 42 characters
 
 
 
-<a name="0x3_bitcoin_address_ErrorInvalidScriptVersion"></a>
-
-
-
-<pre><code><b>const</b> <a href="bitcoin_address.md#0x3_bitcoin_address_ErrorInvalidScriptVersion">ErrorInvalidScriptVersion</a>: u64 = 2;
-</code></pre>
-
-
-
 <a name="0x3_bitcoin_address_P2PKH_ADDR_DECIMAL_PREFIX"></a>
 
 
diff --git a/crates/rooch-framework/doc/decoding.md b/crates/rooch-framework/doc/decoding.md
index 61397f28f8..e015acc378 100644
--- a/crates/rooch-framework/doc/decoding.md
+++ b/crates/rooch-framework/doc/decoding.md
@@ -6,6 +6,7 @@
 Module which defines decoding functions.
 
 
+-  [Constants](#@Constants_0)
 -  [Function `base58`](#0x3_decoding_base58)
 -  [Function `base58check`](#0x3_decoding_base58check)
 
@@ -14,6 +15,21 @@ Module which defines decoding functions.
 
 
 
+<a name="@Constants_0"></a>
+
+## Constants
+
+
+<a name="0x3_decoding_ErrorDecodeFailed"></a>
+
+Failed to decode an address
+
+
+<pre><code><b>const</b> <a href="decoding.md#0x3_decoding_ErrorDecodeFailed">ErrorDecodeFailed</a>: u64 = 1;
+</code></pre>
+
+
+
 <a name="0x3_decoding_base58"></a>
 
 ## Function `base58`
diff --git a/crates/rooch-framework/doc/ecdsa_k1_recoverable.md b/crates/rooch-framework/doc/ecdsa_k1_recoverable.md
index 4c4f181fb5..1232d0b2c7 100644
--- a/crates/rooch-framework/doc/ecdsa_k1_recoverable.md
+++ b/crates/rooch-framework/doc/ecdsa_k1_recoverable.md
@@ -83,6 +83,16 @@ Error if the public key cannot be recovered from the signature.
 
 
 
+<a name="0x3_ecdsa_k1_recoverable_ErrorInvalidHashType"></a>
+
+Invalid hash function
+
+
+<pre><code><b>const</b> <a href="ecdsa_k1_recoverable.md#0x3_ecdsa_k1_recoverable_ErrorInvalidHashType">ErrorInvalidHashType</a>: u64 = 4;
+</code></pre>
+
+
+
 <a name="0x3_ecdsa_k1_recoverable_KECCAK256"></a>
 
 Hash function name that are valid for ecrecover and verify.
diff --git a/crates/rooch-framework/doc/encoding.md b/crates/rooch-framework/doc/encoding.md
index 0333675c86..d97f797559 100644
--- a/crates/rooch-framework/doc/encoding.md
+++ b/crates/rooch-framework/doc/encoding.md
@@ -6,6 +6,7 @@
 Module which defines encoding functions.
 
 
+-  [Constants](#@Constants_0)
 -  [Function `base58`](#0x3_encoding_base58)
 -  [Function `base58check`](#0x3_encoding_base58check)
 -  [Function `bech32`](#0x3_encoding_bech32)
@@ -17,6 +18,51 @@ Module which defines encoding functions.
 
 
 
+<a name="@Constants_0"></a>
+
+## Constants
+
+
+<a name="0x3_encoding_ErrorExcessiveScriptSize"></a>
+
+Excessive script size
+
+
+<pre><code><b>const</b> <a href="encoding.md#0x3_encoding_ErrorExcessiveScriptSize">ErrorExcessiveScriptSize</a>: u64 = 2;
+</code></pre>
+
+
+
+<a name="0x3_encoding_ErrorInvalidData"></a>
+
+Invalid data
+
+
+<pre><code><b>const</b> <a href="encoding.md#0x3_encoding_ErrorInvalidData">ErrorInvalidData</a>: u64 = 3;
+</code></pre>
+
+
+
+<a name="0x3_encoding_ErrorInvalidPubkey"></a>
+
+Invalid publich key
+
+
+<pre><code><b>const</b> <a href="encoding.md#0x3_encoding_ErrorInvalidPubkey">ErrorInvalidPubkey</a>: u64 = 1;
+</code></pre>
+
+
+
+<a name="0x3_encoding_ErrorInvalidScriptVersion"></a>
+
+Invalid script version
+
+
+<pre><code><b>const</b> <a href="encoding.md#0x3_encoding_ErrorInvalidScriptVersion">ErrorInvalidScriptVersion</a>: u64 = 4;
+</code></pre>
+
+
+
 <a name="0x3_encoding_base58"></a>
 
 ## Function `base58`
diff --git a/crates/rooch-framework/sources/bcs.move b/crates/rooch-framework/sources/bcs.move
index e80e7a1674..46a1037d34 100644
--- a/crates/rooch-framework/sources/bcs.move
+++ b/crates/rooch-framework/sources/bcs.move
@@ -9,6 +9,9 @@
 /// a general conversion back-and-force is needed, consider the `moveos_std::Any` type which preserves invariants.
 module rooch_framework::bcs {
 
+    /// The request Move type is not match with input Move type.
+    const ErrorTypeNotMatch: u64 = 1;
+
     public fun to_bytes<MoveValue>(v: &MoveValue): vector<u8> {
         std::bcs::to_bytes(v)
     }
diff --git a/crates/rooch-framework/sources/crypto/decoding.move b/crates/rooch-framework/sources/crypto/decoding.move
index c3d3b305be..894c25ac64 100644
--- a/crates/rooch-framework/sources/crypto/decoding.move
+++ b/crates/rooch-framework/sources/crypto/decoding.move
@@ -3,6 +3,10 @@
 
 /// Module which defines decoding functions.
 module rooch_framework::decoding {
+
+   /// Failed to decode an address
+   const ErrorDecodeFailed: u64 = 1;
+   
    /// @param encoded_address_bytes: encoded Bitcoin address bytes on the Bitcoin network 
    /// Decode the Bitcoin address bytes with Base58 algorithm and returns a raw address bytes
    native public fun base58(encoded_address_bytes: &vector<u8>): vector<u8>;
diff --git a/crates/rooch-framework/sources/crypto/ecdsa_k1.move b/crates/rooch-framework/sources/crypto/ecdsa_k1.move
index d430babefb..04ac81d65e 100644
--- a/crates/rooch-framework/sources/crypto/ecdsa_k1.move
+++ b/crates/rooch-framework/sources/crypto/ecdsa_k1.move
@@ -2,6 +2,7 @@
 // SPDX-License-Identifier: Apache-2.0
 
 module rooch_framework::ecdsa_k1 {
+
     /// constant codes
     const ECDSA_K1_TO_BITCOIN_VALIDATOR_ID_LENGTH: u64 = 1;
     const ECDSA_K1_COMPRESSED_PUBKEY_LENGTH: u64 = 33;
@@ -62,7 +63,7 @@ module rooch_framework::ecdsa_k1 {
     }
 
     #[test]
-    #[expected_failure(abort_code = ErrorInvalidSignature)]
+    #[expected_failure(location=Self, abort_code = 65537)] // std::error::invalid_argument(ErrorInvalidSignature)
     fun test_verify_fails_invalid_sig() {
         let msg = x"00010203";
         let pubkey = x"033e99a541db69bd32040dfe5037fbf5210dafa8151a71e21c5204b05d95ce0a62";
@@ -71,7 +72,7 @@ module rooch_framework::ecdsa_k1 {
     }
 
     #[test]
-    #[expected_failure(abort_code = ErrorInvalidPubKey)]
+    #[expected_failure(location=Self, abort_code = 65538)] // std::error::invalid_argument(ErrorInvalidPubKey)
     fun test_verify_fails_invalid_pubkey() {
         let msg = x"00010203";
         let pubkey = x"";
diff --git a/crates/rooch-framework/sources/crypto/ecdsa_k1_recoverable.move b/crates/rooch-framework/sources/crypto/ecdsa_k1_recoverable.move
index f00a3aff08..0e6361f25c 100644
--- a/crates/rooch-framework/sources/crypto/ecdsa_k1_recoverable.move
+++ b/crates/rooch-framework/sources/crypto/ecdsa_k1_recoverable.move
@@ -19,6 +19,9 @@ module rooch_framework::ecdsa_k1_recoverable {
     /// Error if the public key is invalid.
     const ErrorInvalidPubKey: u64 = 3;
 
+    /// Invalid hash function
+    const ErrorInvalidHashType: u64 = 4;
+
     /// built-in functions
     public fun public_key_length(): u64 {
         ECDSA_K1_RECOVERABLE_COMPRESSED_PUBKEY_LENGTH
@@ -77,7 +80,7 @@ module rooch_framework::ecdsa_k1_recoverable {
     }
 
     #[test]
-    #[expected_failure(abort_code = ErrorFailToRecoverPubKey)]
+    #[expected_failure(location=Self, abort_code = 720897)]  // std::error::invalid_argument(ErrorFailToRecoverPubKey)
     fun test_ecrecover_pubkey_fail_to_recover() {
         let msg = x"00";
         let sig = x"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
@@ -85,7 +88,7 @@ module rooch_framework::ecdsa_k1_recoverable {
     }
 
     #[test]
-    #[expected_failure(abort_code = ErrorInvalidSignature)]
+    #[expected_failure(location=Self, abort_code = 65538)] // std::error::invalid_argument(ErrorInvalidSignature)
     fun test_ecrecover_pubkey_invalid_sig() {
         let msg = b"Hello, world!";
         // incorrect length sig
@@ -94,7 +97,7 @@ module rooch_framework::ecdsa_k1_recoverable {
     }
 
     #[test]
-    #[expected_failure(abort_code = ErrorInvalidSignature)]
+    #[expected_failure(location=Self, abort_code = 65538)] // std::error::invalid_argument(ErrorInvalidSignature) 
     fun test_verify_fails_invalid_sig() {
         let msg = b"Hello, world!";
         let sig = x"";
@@ -118,7 +121,7 @@ module rooch_framework::ecdsa_k1_recoverable {
     }
 
     #[test]
-    #[expected_failure(abort_code = ErrorInvalidPubKey)]
+    #[expected_failure(location=Self, abort_code = 65539)] // std::error::invalid_argument(ErrorInvalidSignature) 
     fun test_decompress_pubkey_invalid_pubkey() {
         let pubkey = x"013e99a541db69bd32040dfe5037fbf5210dafa8151a71e21c5204b05d95ce0a62";
         decompress_pubkey(&pubkey);
diff --git a/crates/rooch-framework/sources/crypto/encoding.move b/crates/rooch-framework/sources/crypto/encoding.move
index b332d0b03c..0b681cdba5 100644
--- a/crates/rooch-framework/sources/crypto/encoding.move
+++ b/crates/rooch-framework/sources/crypto/encoding.move
@@ -3,6 +3,19 @@
 
 /// Module which defines encoding functions.
 module rooch_framework::encoding {
+
+   /// Invalid publich key
+   const ErrorInvalidPubkey: u64 = 1;
+
+   /// Excessive script size
+   const ErrorExcessiveScriptSize: u64 = 2;
+
+   /// Invalid data
+   const ErrorInvalidData: u64 = 3;
+
+   /// Invalid script version
+   const ErrorInvalidScriptVersion: u64 = 4;
+   
    /// @param address_bytes: address bytes on the Bitcoin network 
    /// Encode the address bytes with Base58 algorithm and returns an encoded Bitcoin address
    native public fun base58(address_bytes: &vector<u8>): vector<u8>;
diff --git a/crates/rooch-framework/sources/crypto/schnorr.move b/crates/rooch-framework/sources/crypto/schnorr.move
index 8fd7690a8f..ace97d3fdb 100644
--- a/crates/rooch-framework/sources/crypto/schnorr.move
+++ b/crates/rooch-framework/sources/crypto/schnorr.move
@@ -42,7 +42,7 @@ module rooch_framework::schnorr {
     ): bool;
 
     #[test]
-    #[expected_failure(abort_code = ErrorInvalidSignature)]
+    #[expected_failure(location=Self, abort_code = 65537)] // std::error::invalid_argument(ErrorInvalidSignature)
     public fun test_schnorr_invalid_sig() {
       let msg = x"00010203";
       let pk = x"3e99a541db69bd32040dfe5037fbf5210dafa8151a71e21c5204b05d95ce0a62";
@@ -62,7 +62,7 @@ module rooch_framework::schnorr {
     }
 
     #[test]
-    #[expected_failure(abort_code = ErrorInvalidPubKey)]
+    #[expected_failure(location=Self, abort_code = 65538)] // std::error::invalid_argument(ErrorInvalidPubKey)
     public fun test_schnorr_invalid_pubkey() {
         let msg = x"00010203";
         let invalid_pk = x"";
diff --git a/crates/rooch-framework/src/natives/gas_parameter/move_module.rs b/crates/rooch-framework/src/natives/gas_parameter/move_module.rs
index 314b866ce7..6cc7fce22f 100644
--- a/crates/rooch-framework/src/natives/gas_parameter/move_module.rs
+++ b/crates/rooch-framework/src/natives/gas_parameter/move_module.rs
@@ -7,8 +7,8 @@ use moveos_stdlib::natives::moveos_stdlib::move_module::GasParameters;
 crate::natives::gas_parameter::native::define_gas_parameters_for_natives!(GasParameters, "move_module", [
     [.module_name_inner.base, "module_name_inner.base", (5 + 1) * MUL],
     [.module_name_inner.per_byte_in_str, "module_name_inner.per_byte_in_str", (5 + 1) * MUL],
-    [.verify_modules_inner.base, "verify_modules_inner.base", (5 + 1) * MUL],
-    [.verify_modules_inner.per_byte, "verify_modules_inner.per_byte", (5 + 1) * MUL],
+    [.sort_and_verify_modules_inner.base, "sort_and_verify_modules_inner.base", (5 + 1) * MUL],
+    [.sort_and_verify_modules_inner.per_byte, "sort_and_verify_modules_inner.per_byte", (5 + 1) * MUL],
     [.request_init_functions.base, "request_init_functions.base", (5 + 1) * MUL],
     [.request_init_functions.per_byte, "request_init_functions.per_byte", (5 + 1) * MUL],
     [.check_compatibililty_inner.base, "check_compatibililty_inner.base", (5 + 1) * MUL],
diff --git a/crates/rooch-framework/src/natives/rooch_framework/bcs.rs b/crates/rooch-framework/src/natives/rooch_framework/bcs.rs
index 1bbd7b3081..639dc40335 100644
--- a/crates/rooch-framework/src/natives/rooch_framework/bcs.rs
+++ b/crates/rooch-framework/src/natives/rooch_framework/bcs.rs
@@ -12,6 +12,8 @@ use move_vm_types::{
 use smallvec::smallvec;
 use std::collections::VecDeque;
 
+const E_TYPE_NOT_MATCH: u64 = 1;
+
 #[derive(Debug, Clone)]
 pub struct FromBytesGasParameters {
     pub base: InternalGas,
@@ -27,7 +29,7 @@ impl FromBytesGasParameters {
 /// Bytes are in BCS (Binary Canonical Serialization) format.
 #[inline]
 fn native_from_bytes(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -35,7 +37,7 @@ fn native_from_bytes(
     debug_assert_eq!(ty_args.len(), 1);
     debug_assert_eq!(args.len(), 1);
 
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     // TODO(Gas): charge for getting the layout
     let layout = context.type_to_type_layout(&ty_args[0])?.ok_or_else(|| {
@@ -49,8 +51,10 @@ fn native_from_bytes(
     let val = match Value::simple_deserialize(&bytes, &layout) {
         Some(val) => val,
         None => {
-            // TODO(gas): charge the gas for the failure.
-            return Err(PartialVMError::new(StatusCode::VALUE_DESERIALIZATION_ERROR));
+            return Ok(NativeResult::err(
+                cost,
+                moveos_types::move_std::error::invalid_argument(E_TYPE_NOT_MATCH),
+            ));
         }
     };
     // TODO(gas): charge gas for deserialization
diff --git a/crates/rooch-framework/src/natives/rooch_framework/crypto/decoding.rs b/crates/rooch-framework/src/natives/rooch_framework/crypto/decoding.rs
index 5dfffe5115..8ca8aa2285 100644
--- a/crates/rooch-framework/src/natives/rooch_framework/crypto/decoding.rs
+++ b/crates/rooch-framework/src/natives/rooch_framework/crypto/decoding.rs
@@ -14,7 +14,7 @@ use move_vm_types::{
 use smallvec::smallvec;
 use std::collections::VecDeque;
 
-pub const DECODE_FAILED: u64 = 1;
+pub const E_DECODE_FAILED: u64 = 1;
 
 /***************************************************************************************************
  * native fun base58
@@ -24,7 +24,7 @@ pub const DECODE_FAILED: u64 = 1;
  *              + decoding_base58_data_cost_per_block * num_blocks     | cost depends on number of blocks in message
  **************************************************************************************************/
 pub fn native_base58(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     _context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -34,14 +34,14 @@ pub fn native_base58(
 
     // TODO(Gas): Charge the arg size dependent costs
 
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     let encoded_address_bytes = pop_arg!(args, VectorRef);
 
     let Ok(bs58_raw_bytes) = bs58::decode(encoded_address_bytes.as_bytes_ref().to_vec())
         .into_vec()
     else {
-        return Ok(NativeResult::err(cost, DECODE_FAILED));
+        return Ok(NativeResult::err(cost, moveos_types::move_std::error::invalid_argument(E_DECODE_FAILED)));
     };
 
     Ok(NativeResult::ok(
@@ -58,7 +58,7 @@ pub fn native_base58(
  *              + decoding_base58check_data_cost_per_block * num_blocks     | cost depends on number of blocks in message
  **************************************************************************************************/
 pub fn native_base58check(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     _context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -68,7 +68,7 @@ pub fn native_base58check(
 
     // TODO(Gas): Charge the arg size dependent costs
 
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     let version_byte = pop_arg!(args, u8);
     let encoded_address_bytes = pop_arg!(args, VectorRef);
@@ -77,7 +77,7 @@ pub fn native_base58check(
         .with_check(Some(version_byte))
         .into_vec()
     else {
-        return Ok(NativeResult::err(cost, DECODE_FAILED));
+        return Ok(NativeResult::err(cost, moveos_types::move_std::error::invalid_argument(E_DECODE_FAILED)));
     };
 
     Ok(NativeResult::ok(
diff --git a/crates/rooch-framework/src/natives/rooch_framework/crypto/ecdsa_k1.rs b/crates/rooch-framework/src/natives/rooch_framework/crypto/ecdsa_k1.rs
index d0009e58cc..99605dc340 100644
--- a/crates/rooch-framework/src/natives/rooch_framework/crypto/ecdsa_k1.rs
+++ b/crates/rooch-framework/src/natives/rooch_framework/crypto/ecdsa_k1.rs
@@ -19,14 +19,14 @@ use move_vm_types::{
 use smallvec::smallvec;
 use std::collections::VecDeque;
 
-pub const INVALID_SIGNATURE: u64 = 1;
-pub const INVALID_PUBKEY: u64 = 2;
+pub const E_INVALID_SIGNATURE: u64 = 1;
+pub const E_INVALID_PUBKEY: u64 = 2;
 
 pub const KECCAK256: u8 = 0;
 pub const SHA256: u8 = 1;
 
 pub fn native_verify(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     _context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -46,14 +46,14 @@ pub fn native_verify(
 
     // TODO(Gas): Charge the arg size dependent costs
 
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     let Ok(sig) = <Secp256k1Signature as ToFromBytes>::from_bytes(&signature_bytes_ref) else {
-        return Ok(NativeResult::err(cost, INVALID_SIGNATURE));
+        return Ok(NativeResult::err(cost, moveos_types::move_std::error::invalid_argument(E_INVALID_SIGNATURE)));
     };
 
     let Ok(public_key) = <Secp256k1PublicKey as ToFromBytes>::from_bytes(&public_key_bytes_ref) else {
-        return Ok(NativeResult::err(cost, INVALID_PUBKEY));
+        return Ok(NativeResult::err(cost, moveos_types::move_std::error::invalid_argument(E_INVALID_PUBKEY)));
     };
 
     let result = match hash {
diff --git a/crates/rooch-framework/src/natives/rooch_framework/crypto/ecdsa_k1_recoverable.rs b/crates/rooch-framework/src/natives/rooch_framework/crypto/ecdsa_k1_recoverable.rs
index da48ebca70..0bb5e15a52 100644
--- a/crates/rooch-framework/src/natives/rooch_framework/crypto/ecdsa_k1_recoverable.rs
+++ b/crates/rooch-framework/src/natives/rooch_framework/crypto/ecdsa_k1_recoverable.rs
@@ -3,7 +3,6 @@
 
 use crate::natives::helpers::{make_module_natives, make_native};
 use fastcrypto::{
-    error::FastCryptoError,
     hash::{Keccak256, Sha256},
     secp256k1::{recoverable::Secp256k1RecoverableSignature, Secp256k1PublicKey},
     traits::{RecoverableSignature, ToFromBytes},
@@ -20,15 +19,16 @@ use move_vm_types::{
 use smallvec::smallvec;
 use std::collections::VecDeque;
 
-pub const FAIL_TO_RECOVER_PUBKEY: u64 = 1;
-pub const INVALID_SIGNATURE: u64 = 2;
-pub const INVALID_PUBKEY: u64 = 3;
+pub const E_FAIL_TO_RECOVER_PUBKEY: u64 = 1;
+pub const E_INVALID_SIGNATURE: u64 = 2;
+pub const E_INVALID_PUBKEY: u64 = 3;
+pub const E_INVALID_HASH_TYPE: u64 = 4;
 
 pub const KECCAK256: u8 = 0;
 pub const SHA256: u8 = 1;
 
 pub fn native_ecrecover(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     _context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -45,16 +45,21 @@ pub fn native_ecrecover(
 
     // TODO(Gas): Charge the arg size dependent costs
 
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     let Ok(sig) = <Secp256k1RecoverableSignature as ToFromBytes>::from_bytes(&signature_ref) else {
-        return Ok(NativeResult::err(cost, INVALID_SIGNATURE));
+        return Ok(NativeResult::err(cost, moveos_types::move_std::error::invalid_argument(E_INVALID_SIGNATURE)));
     };
 
     let pk = match hash {
         KECCAK256 => sig.recover_with_hash::<Keccak256>(&msg_ref),
         SHA256 => sig.recover_with_hash::<Sha256>(&msg_ref),
-        _ => Err(FastCryptoError::InvalidInput), // We should never reach here
+        _ => {
+            return Ok(NativeResult::err(
+                cost,
+                moveos_types::move_std::error::invalid_argument(E_INVALID_HASH_TYPE),
+            ))
+        } // We should never reach here
     };
 
     match pk {
@@ -62,12 +67,15 @@ pub fn native_ecrecover(
             cost,
             smallvec![Value::vector_u8(pk.as_bytes().to_vec())],
         )),
-        Err(_) => Ok(NativeResult::err(cost, FAIL_TO_RECOVER_PUBKEY)),
+        Err(_) => Ok(NativeResult::err(
+            cost,
+            moveos_types::move_std::error::internal(E_FAIL_TO_RECOVER_PUBKEY),
+        )),
     }
 }
 
 pub fn native_decompress_pubkey(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     _context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -79,7 +87,7 @@ pub fn native_decompress_pubkey(
     let pubkey_ref = pubkey.as_bytes_ref();
 
     // TODO(Gas): Charge the arg size dependent costs
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     match Secp256k1PublicKey::from_bytes(&pubkey_ref) {
         Ok(pubkey) => {
@@ -89,12 +97,15 @@ pub fn native_decompress_pubkey(
                 smallvec![Value::vector_u8(uncompressed.to_vec())],
             ))
         }
-        Err(_) => Ok(NativeResult::err(cost, INVALID_PUBKEY)),
+        Err(_) => Ok(NativeResult::err(
+            cost,
+            moveos_types::move_std::error::invalid_argument(E_INVALID_PUBKEY),
+        )),
     }
 }
 
 pub fn native_verify(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     _context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -112,10 +123,10 @@ pub fn native_verify(
 
     // TODO(Gas): Charge the arg size dependent costs
 
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     let Ok(sig) = <Secp256k1RecoverableSignature as ToFromBytes>::from_bytes(&signature_bytes_ref) else {
-        return Ok(NativeResult::err(cost, INVALID_SIGNATURE));
+        return Ok(NativeResult::err(cost, moveos_types::move_std::error::invalid_argument(E_INVALID_SIGNATURE)));
     };
 
     let pk = match hash {
diff --git a/crates/rooch-framework/src/natives/rooch_framework/crypto/ed25519.rs b/crates/rooch-framework/src/natives/rooch_framework/crypto/ed25519.rs
index 037a84e9a3..95e76a606c 100644
--- a/crates/rooch-framework/src/natives/rooch_framework/crypto/ed25519.rs
+++ b/crates/rooch-framework/src/natives/rooch_framework/crypto/ed25519.rs
@@ -28,7 +28,7 @@ use std::collections::VecDeque;
  *              + ed25519_ed25519_verify_msg_cost_per_block * block_size | cost depends on number of blocks in message
  **************************************************************************************************/
 pub fn native_verify(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     _context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -38,7 +38,7 @@ pub fn native_verify(
 
     // TODO(Gas): Charge the arg size dependent costs
 
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     let msg = pop_arg!(args, VectorRef);
     let msg_ref = msg.as_bytes_ref();
diff --git a/crates/rooch-framework/src/natives/rooch_framework/crypto/encoding.rs b/crates/rooch-framework/src/natives/rooch_framework/crypto/encoding.rs
index 02a8f0b563..59334e0b43 100644
--- a/crates/rooch-framework/src/natives/rooch_framework/crypto/encoding.rs
+++ b/crates/rooch-framework/src/natives/rooch_framework/crypto/encoding.rs
@@ -18,10 +18,10 @@ use move_vm_types::{
 use smallvec::smallvec;
 use std::collections::VecDeque;
 
-pub const INVALID_PUBKEY: u64 = 1;
-pub const EXCESSIVE_SCRIPT_SIZE: u64 = 2;
-pub const INVALID_DATA: u64 = 3;
-pub const INVALID_SCRIPT_VERSION: u64 = 4;
+pub const E_INVALID_PUBKEY: u64 = 1;
+pub const E_EXCESSIVE_SCRIPT_SIZE: u64 = 2;
+pub const E_INVALID_DATA: u64 = 3;
+pub const E_INVALID_SCRIPT_VERSION: u64 = 4;
 
 /***************************************************************************************************
  * native fun base58
@@ -31,7 +31,7 @@ pub const INVALID_SCRIPT_VERSION: u64 = 4;
  *              + encoding_base58_data_cost_per_block * num_blocks     | cost depends on number of blocks in message
  **************************************************************************************************/
 pub fn native_base58(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     _context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -41,7 +41,7 @@ pub fn native_base58(
 
     // TODO(Gas): Charge the arg size dependent costs
 
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     let address_bytes = pop_arg!(args, VectorRef);
 
@@ -61,7 +61,7 @@ pub fn native_base58(
  *              + encoding_base58check_data_cost_per_block * num_blocks     | cost depends on number of blocks in message
  **************************************************************************************************/
 pub fn native_base58check(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     _context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -71,7 +71,7 @@ pub fn native_base58check(
 
     // TODO(Gas): Charge the arg size dependent costs
 
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     let version_byte = pop_arg!(args, u8);
     let address_bytes = pop_arg!(args, VectorRef);
@@ -94,7 +94,7 @@ pub fn native_base58check(
  *              + encoding_bech32_data_cost_per_block * num_blocks     | cost depends on number of blocks in message
  **************************************************************************************************/
 pub fn native_bech32(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     _context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -104,14 +104,14 @@ pub fn native_bech32(
 
     // TODO(Gas): Charge the arg size dependent costs
 
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     let version = pop_arg!(args, u8);
     let public_key = pop_arg!(args, VectorRef);
 
     // Version 0 for bech32 encoding and 1-16 are for bech32m encoding
     let Ok(version) = u5::try_from_u8(version) else {
-        return Ok(NativeResult::err(cost, INVALID_DATA));
+        return Ok(NativeResult::err(cost, E_INVALID_DATA));
     };
 
     let Ok(witness_program) = WitnessProgram::new(
@@ -119,7 +119,7 @@ pub fn native_bech32(
         public_key.as_bytes_ref().to_vec(),
         Bech32Network::Bitcoin, // TODO network selection
     ) else {
-        return Ok(NativeResult::err(cost, INVALID_SCRIPT_VERSION));
+        return Ok(NativeResult::err(cost, moveos_types::move_std::error::invalid_argument(E_INVALID_SCRIPT_VERSION)));
     };
 
     let address = witness_program.to_address();
@@ -139,7 +139,7 @@ pub fn native_bech32(
  *              + encoding_p2pkh_data_cost_per_block * num_blocks     | cost depends on number of blocks in message
  **************************************************************************************************/
 pub fn native_p2pkh(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     _context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -149,13 +149,13 @@ pub fn native_p2pkh(
 
     // TODO(Gas): Charge the arg size dependent costs
 
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     let public_key = pop_arg!(args, VectorRef);
     let public_key_bytes_ref = public_key.as_bytes_ref();
 
     let Ok(public_key) = <Secp256k1PublicKey as ToFromBytes>::from_bytes(&public_key_bytes_ref) else {
-        return Ok(NativeResult::err(cost, INVALID_PUBKEY));
+        return Ok(NativeResult::err(cost, moveos_types::move_std::error::invalid_argument(E_INVALID_PUBKEY)));
     };
 
     let bitcoin_public_key = PublicKey::new(public_key.pubkey);
@@ -178,7 +178,7 @@ pub fn native_p2pkh(
  *              + encoding_p2sh_data_cost_per_block * num_blocks     | cost depends on number of blocks in message
  **************************************************************************************************/
 pub fn native_p2sh(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     _context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -188,13 +188,13 @@ pub fn native_p2sh(
 
     // TODO(Gas): Charge the arg size dependent costs
 
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     let public_key = pop_arg!(args, VectorRef);
     let public_key_bytes_ref = public_key.as_bytes_ref();
 
     let Ok(public_key) = <Secp256k1PublicKey as ToFromBytes>::from_bytes(&public_key_bytes_ref) else {
-        return Ok(NativeResult::err(cost, INVALID_PUBKEY));
+        return Ok(NativeResult::err(cost, moveos_types::move_std::error::invalid_argument(E_INVALID_PUBKEY)));
     };
 
     let bitcoin_public_key = PublicKey::new(public_key.pubkey);
@@ -207,7 +207,7 @@ pub fn native_p2sh(
         redeem_script,
         Network::Bitcoin, // TODO network selection
     ) else {
-        return Ok(NativeResult::err(cost, EXCESSIVE_SCRIPT_SIZE));
+        return Ok(NativeResult::err(cost, moveos_types::move_std::error::internal(E_EXCESSIVE_SCRIPT_SIZE)));
     };
     let p2sh_address_bytes = p2sh_address.to_string().as_bytes().to_vec();
 
diff --git a/crates/rooch-framework/src/natives/rooch_framework/crypto/schnorr.rs b/crates/rooch-framework/src/natives/rooch_framework/crypto/schnorr.rs
index 413d533614..c74d02cf28 100644
--- a/crates/rooch-framework/src/natives/rooch_framework/crypto/schnorr.rs
+++ b/crates/rooch-framework/src/natives/rooch_framework/crypto/schnorr.rs
@@ -20,14 +20,14 @@ use rust_secp256k1::schnorr::Signature;
 use smallvec::smallvec;
 use std::collections::VecDeque;
 
-pub const INVALID_SIGNATURE: u64 = 1;
-pub const INVALID_PUBKEY: u64 = 2;
+pub const E_INVALID_SIGNATURE: u64 = 1;
+pub const E_INVALID_PUBKEY: u64 = 2;
 
 pub const KECCAK256: u8 = 0;
 pub const SHA256: u8 = 1;
 
 pub fn native_verify(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     _context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -46,14 +46,14 @@ pub fn native_verify(
 
     // TODO(Gas): Charge the arg size dependent costs
 
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     let Ok(sig) = Signature::from_slice(&signature_bytes_ref) else {
-        return Ok(NativeResult::err(cost, INVALID_SIGNATURE));
+        return Ok(NativeResult::err(cost, moveos_types::move_std::error::invalid_argument(E_INVALID_SIGNATURE)));
     };
 
     let Ok(public_key) = <SchnorrPublicKey as ToFromBytes>::from_bytes(&public_key_bytes_ref) else {
-        return Ok(NativeResult::err(cost, INVALID_PUBKEY));
+        return Ok(NativeResult::err(cost, moveos_types::move_std::error::invalid_argument(E_INVALID_PUBKEY)));
     };
 
     let sign = SchnorrSignature::from(&sig);
diff --git a/examples/publish_modules/sources/publish.move b/examples/publish_modules/sources/publish.move
index bc494f0c2a..d86e542571 100644
--- a/examples/publish_modules/sources/publish.move
+++ b/examples/publish_modules/sources/publish.move
@@ -47,7 +47,7 @@ module rooch_examples::publish {
         let module_bytes: vector<u8> = x"a11ceb0b060000000b010006020608030e26043406053a32076c7d08e9014006a902220acb02050cd002560da6030200000101010200030c00020400000005000100000600010000070201000008030400010907080108010a09010108010b0a0b0108040605060606010708010002070801060c0106080101030107080001080002070801050107090003070801060c090002060801050106090007636f756e7465720f6163636f756e745f73746f7261676507636f6e7465787407436f756e74657207436f6e7465787408696e63726561736509696e6372656173655f04696e69740576616c756511676c6f62616c5f626f72726f775f6d75740e676c6f62616c5f6d6f76655f746f0d676c6f62616c5f626f72726f77000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000020520000000000000000000000000000000000000000000000000000000000000004200020108030001040001030b0011010201010000050d0b00070038000c010a01100014060100000000000000160b010f0015020200000001060b000b0106000000000000000012003801020301000001060b000700380210001402000000";
         let m: MoveModule = move_module::new(module_bytes);
         let modules = vector::singleton(m);
-        let (module_names, _module_names_with_init_fn) = move_module::verify_modules(&modules, addr);
+        let (module_names, _module_names_with_init_fn) = move_module::sort_and_verify_modules(&modules, addr);
         debug::print(&module_names);
         context::drop_test_context(ctx);  
     }
diff --git a/moveos/moveos-stdlib-builder/Cargo.toml b/moveos/moveos-stdlib-builder/Cargo.toml
index 6f350b5b02..eaffbfe504 100644
--- a/moveos/moveos-stdlib-builder/Cargo.toml
+++ b/moveos/moveos-stdlib-builder/Cargo.toml
@@ -46,6 +46,5 @@ move-errmapgen = { workspace = true }
 move-docgen = { workspace = true }
 move-model = { workspace = true }
 
-
 moveos-types = { workspace = true }
 moveos-verifier = { workspace = true }
diff --git a/moveos/moveos-stdlib-builder/src/dependency_order.rs b/moveos/moveos-stdlib-builder/src/dependency_order.rs
index ac930d1a23..c67886a3b7 100644
--- a/moveos/moveos-stdlib-builder/src/dependency_order.rs
+++ b/moveos/moveos-stdlib-builder/src/dependency_order.rs
@@ -67,7 +67,7 @@ impl<'a> DependencyGraph<'a> {
     /// Fails with an error if `self` contains circular dependencies
     pub fn compute_topological_order(&self) -> Result<impl Iterator<Item = &CompiledModule>> {
         match petgraph::algo::toposort(&self.graph, None) {
-            Err(_) => bail!("Circular dependency detected"),
+            Err(_) => bail!("Cyclic dependency detected"),
             Ok(ordered_idxs) => Ok(ordered_idxs.into_iter().map(move |idx| self.modules[idx.0])),
         }
     }
diff --git a/moveos/moveos-stdlib/Cargo.toml b/moveos/moveos-stdlib/Cargo.toml
index 244b3679b0..feb72e9c60 100644
--- a/moveos/moveos-stdlib/Cargo.toml
+++ b/moveos/moveos-stdlib/Cargo.toml
@@ -42,4 +42,5 @@ move-package = { workspace = true }
 move-prover = { workspace = true }
 
 moveos-types = { workspace = true }
-moveos-verifier = { workspace = true }
\ No newline at end of file
+moveos-verifier = { workspace = true }
+moveos-stdlib-builder = { workspace = true }
\ No newline at end of file
diff --git a/moveos/moveos-stdlib/moveos-stdlib/doc/account_storage.md b/moveos/moveos-stdlib/moveos-stdlib/doc/account_storage.md
index b3b6488151..6cc32b346c 100644
--- a/moveos/moveos-stdlib/moveos-stdlib/doc/account_storage.md
+++ b/moveos/moveos-stdlib/moveos-stdlib/doc/account_storage.md
@@ -449,12 +449,12 @@ Publish modules to the account's storage
     <b>let</b> <a href="account_storage.md#0x2_account_storage">account_storage</a> = <a href="account_storage.md#0x2_account_storage_borrow_account_storage_mut">borrow_account_storage_mut</a>(ctx, account_address);
     <b>let</b> i = 0;
     <b>let</b> len = <a href="_length">vector::length</a>(&modules);
-    <b>let</b> (module_names, module_names_with_init_fn) = <a href="move_module.md#0x2_move_module_verify_modules">move_module::verify_modules</a>(&modules, account_address);
+    <b>let</b> (module_names, module_names_with_init_fn) = <a href="move_module.md#0x2_move_module_sort_and_verify_modules">move_module::sort_and_verify_modules</a>(&modules, account_address);
 
     <b>let</b> upgrade_flag = <b>false</b>;
     <b>while</b> (i &lt; len) {
         <b>let</b> name = <a href="_pop_back">vector::pop_back</a>(&<b>mut</b> module_names);
-        <b>let</b> m = <a href="_pop_back">vector::pop_back</a>(&<b>mut</b> modules);
+        <b>let</b> m = <a href="account_storage.md#0x2_account_storage_pop_module_by_name">pop_module_by_name</a>(&<b>mut</b> modules, name);
 
         // The <b>module</b> already <b>exists</b>, which means we are upgrading the <b>module</b>
         <b>if</b> (<a href="table.md#0x2_table_contains">table::contains</a>(&<a href="account_storage.md#0x2_account_storage">account_storage</a>.modules, name)) {
@@ -511,8 +511,7 @@ The order of modules must be sorted by dependency order.
         <a href="_push_back">vector::push_back</a>(&<b>mut</b> module_vec, m);
         i = i + 1;
     };
-    // The input modules are sorted by dependency order which must not be changed.
-    <a href="_reverse">vector::reverse</a>(&<b>mut</b> module_vec);
+
     <a href="account_storage.md#0x2_account_storage_publish_modules">publish_modules</a>(ctx, account, module_vec);
 }
 </code></pre>
diff --git a/moveos/moveos-stdlib/moveos-stdlib/doc/bcs.md b/moveos/moveos-stdlib/moveos-stdlib/doc/bcs.md
index 4d900d6900..3eed90b185 100644
--- a/moveos/moveos-stdlib/moveos-stdlib/doc/bcs.md
+++ b/moveos/moveos-stdlib/moveos-stdlib/doc/bcs.md
@@ -10,6 +10,7 @@ function because this can violate implicit struct invariants, therefore only pri
 a general conversion back-and-force is needed, consider the <code>moveos_std::Any</code> type which preserves invariants.
 
 
+-  [Constants](#@Constants_0)
 -  [Function `to_bytes`](#0x2_bcs_to_bytes)
 -  [Function `to_bool`](#0x2_bcs_to_bool)
 -  [Function `to_u8`](#0x2_bcs_to_u8)
@@ -24,6 +25,21 @@ a general conversion back-and-force is needed, consider the <code>moveos_std::An
 
 
 
+<a name="@Constants_0"></a>
+
+## Constants
+
+
+<a name="0x2_bcs_ErrorTypeNotMatch"></a>
+
+The request Move type is not match with input Move type.
+
+
+<pre><code><b>const</b> <a href="bcs.md#0x2_bcs_ErrorTypeNotMatch">ErrorTypeNotMatch</a>: u64 = 1;
+</code></pre>
+
+
+
 <a name="0x2_bcs_to_bytes"></a>
 
 ## Function `to_bytes`
diff --git a/moveos/moveos-stdlib/moveos-stdlib/doc/move_module.md b/moveos/moveos-stdlib/moveos-stdlib/doc/move_module.md
index beda4538ac..9ffcd35cbf 100644
--- a/moveos/moveos-stdlib/moveos-stdlib/doc/move_module.md
+++ b/moveos/moveos-stdlib/moveos-stdlib/doc/move_module.md
@@ -7,9 +7,10 @@
 
 
 -  [Struct `MoveModule`](#0x2_move_module_MoveModule)
+-  [Constants](#@Constants_0)
 -  [Function `new`](#0x2_move_module_new)
 -  [Function `module_name`](#0x2_move_module_module_name)
--  [Function `verify_modules`](#0x2_move_module_verify_modules)
+-  [Function `sort_and_verify_modules`](#0x2_move_module_sort_and_verify_modules)
 -  [Function `check_comatibility`](#0x2_move_module_check_comatibility)
 -  [Function `request_init_functions`](#0x2_move_module_request_init_functions)
 
@@ -46,6 +47,41 @@
 
 </details>
 
+<a name="@Constants_0"></a>
+
+## Constants
+
+
+<a name="0x2_move_module_ErrorAddressNotMatchWithSigner"></a>
+
+Module address is not the same as the signer
+
+
+<pre><code><b>const</b> <a href="move_module.md#0x2_move_module_ErrorAddressNotMatchWithSigner">ErrorAddressNotMatchWithSigner</a>: u64 = 1;
+</code></pre>
+
+
+
+<a name="0x2_move_module_ErrorModuleIncompatible"></a>
+
+Module incompatible with the old ones.
+
+
+<pre><code><b>const</b> <a href="move_module.md#0x2_move_module_ErrorModuleIncompatible">ErrorModuleIncompatible</a>: u64 = 3;
+</code></pre>
+
+
+
+<a name="0x2_move_module_ErrorModuleVerificationError"></a>
+
+Module verification error
+
+
+<pre><code><b>const</b> <a href="move_module.md#0x2_move_module_ErrorModuleVerificationError">ErrorModuleVerificationError</a>: u64 = 2;
+</code></pre>
+
+
+
 <a name="0x2_move_module_new"></a>
 
 ## Function `new`
@@ -96,18 +132,19 @@
 
 </details>
 
-<a name="0x2_move_module_verify_modules"></a>
+<a name="0x2_move_module_sort_and_verify_modules"></a>
 
-## Function `verify_modules`
+## Function `sort_and_verify_modules`
 
-Verify the modules and return their names and names of the modules with init function.
+Sort modules by dependency order and then verify.
+Return their names and names of the modules with init function if sorted dependency order.
 This function will ensure the module's bytecode is valid and the module id is matching the account address.
 Return
-The first vector is the module names of all the modules.
-The second vector is the module names of the modules with init function.
+1. Module names of all the modules. Order of names is not matching the input, but sorted by module dependency order
+2. Module names of the modules with init function.
 
 
-<pre><code><b>public</b> <b>fun</b> <a href="move_module.md#0x2_move_module_verify_modules">verify_modules</a>(modules: &<a href="">vector</a>&lt;<a href="move_module.md#0x2_move_module_MoveModule">move_module::MoveModule</a>&gt;, account_address: <b>address</b>): (<a href="">vector</a>&lt;<a href="_String">string::String</a>&gt;, <a href="">vector</a>&lt;<a href="_String">string::String</a>&gt;)
+<pre><code><b>public</b> <b>fun</b> <a href="move_module.md#0x2_move_module_sort_and_verify_modules">sort_and_verify_modules</a>(modules: &<a href="">vector</a>&lt;<a href="move_module.md#0x2_move_module_MoveModule">move_module::MoveModule</a>&gt;, account_address: <b>address</b>): (<a href="">vector</a>&lt;<a href="_String">string::String</a>&gt;, <a href="">vector</a>&lt;<a href="_String">string::String</a>&gt;)
 </code></pre>
 
 
@@ -116,7 +153,7 @@ The second vector is the module names of the modules with init function.
 <summary>Implementation</summary>
 
 
-<pre><code><b>public</b> <b>fun</b> <a href="move_module.md#0x2_move_module_verify_modules">verify_modules</a>(modules: &<a href="">vector</a>&lt;<a href="move_module.md#0x2_move_module_MoveModule">MoveModule</a>&gt;, account_address: <b>address</b>): (<a href="">vector</a>&lt;String&gt;, <a href="">vector</a>&lt;String&gt;) {
+<pre><code><b>public</b> <b>fun</b> <a href="move_module.md#0x2_move_module_sort_and_verify_modules">sort_and_verify_modules</a>(modules: &<a href="">vector</a>&lt;<a href="move_module.md#0x2_move_module_MoveModule">MoveModule</a>&gt;, account_address: <b>address</b>): (<a href="">vector</a>&lt;String&gt;, <a href="">vector</a>&lt;String&gt;) {
     <b>let</b> bytes_vec = <a href="_empty">vector::empty</a>&lt;<a href="">vector</a>&lt;u8&gt;&gt;();
     <b>let</b> i = 0u64;
     <b>let</b> len = <a href="_length">vector::length</a>(modules);
@@ -124,7 +161,7 @@ The second vector is the module names of the modules with init function.
         <a href="_push_back">vector::push_back</a>(&<b>mut</b> bytes_vec, <a href="_borrow">vector::borrow</a>(modules, i).byte_codes);
         i = i + 1;
     };
-    <a href="move_module.md#0x2_move_module_verify_modules_inner">verify_modules_inner</a>(bytes_vec, account_address)
+    <a href="move_module.md#0x2_move_module_sort_and_verify_modules_inner">sort_and_verify_modules_inner</a>(bytes_vec, account_address)
 }
 </code></pre>
 
diff --git a/moveos/moveos-stdlib/moveos-stdlib/doc/raw_table.md b/moveos/moveos-stdlib/moveos-stdlib/doc/raw_table.md
index 97c14c23cc..ea7cc5990b 100644
--- a/moveos/moveos-stdlib/moveos-stdlib/doc/raw_table.md
+++ b/moveos/moveos-stdlib/moveos-stdlib/doc/raw_table.md
@@ -114,12 +114,22 @@ The key already exists in the table
 
 
 
+<a name="0x2_raw_table_ErrorDuplicateOperation"></a>
+
+Duplicate operation on the table
+
+
+<pre><code><b>const</b> <a href="raw_table.md#0x2_raw_table_ErrorDuplicateOperation">ErrorDuplicateOperation</a>: u64 = 3;
+</code></pre>
+
+
+
 <a name="0x2_raw_table_ErrorNotEmpty"></a>
 
 The table is not empty
 
 
-<pre><code><b>const</b> <a href="raw_table.md#0x2_raw_table_ErrorNotEmpty">ErrorNotEmpty</a>: u64 = 3;
+<pre><code><b>const</b> <a href="raw_table.md#0x2_raw_table_ErrorNotEmpty">ErrorNotEmpty</a>: u64 = 4;
 </code></pre>
 
 
diff --git a/moveos/moveos-stdlib/moveos-stdlib/sources/account_storage.move b/moveos/moveos-stdlib/moveos-stdlib/sources/account_storage.move
index cbc3c02ffd..e011677de4 100644
--- a/moveos/moveos-stdlib/moveos-stdlib/sources/account_storage.move
+++ b/moveos/moveos-stdlib/moveos-stdlib/sources/account_storage.move
@@ -170,18 +170,31 @@ module moveos_std::account_storage {
         exists_module_at_account_storage(account_storage, name) 
     }
 
+    fun pop_module_by_name(modules: &mut vector<MoveModule>, name: String): MoveModule {
+        let i = 0;
+        let len = vector::length(modules);
+        while (i < len) {
+            let m = vector::borrow(modules, i);
+            if (move_module::module_name(m) == name) {
+                return vector::remove(modules, i)
+            };
+            i = i + 1;
+        };
+        abort(0x0) // unreachable.
+    }
+
     /// Publish modules to the account's storage
     public fun publish_modules(ctx: &mut Context, account: &signer, modules: vector<MoveModule>) {
         let account_address = signer::address_of(account);
         let account_storage = borrow_account_storage_mut(ctx, account_address);
         let i = 0;
         let len = vector::length(&modules);
-        let (module_names, module_names_with_init_fn) = move_module::verify_modules(&modules, account_address);
+        let (module_names, module_names_with_init_fn) = move_module::sort_and_verify_modules(&modules, account_address);
         
         let upgrade_flag = false;
         while (i < len) {
             let name = vector::pop_back(&mut module_names);
-            let m = vector::pop_back(&mut modules);   
+            let m = pop_module_by_name(&mut modules, name);   
 
             // The module already exists, which means we are upgrading the module
             if (table::contains(&account_storage.modules, name)) {
@@ -218,8 +231,7 @@ module moveos_std::account_storage {
             vector::push_back(&mut module_vec, m);
             i = i + 1;
         };
-        // The input modules are sorted by dependency order which must not be changed.
-        vector::reverse(&mut module_vec);
+        
         publish_modules(ctx, account, module_vec);
     }
 
diff --git a/moveos/moveos-stdlib/moveos-stdlib/sources/bcs.move b/moveos/moveos-stdlib/moveos-stdlib/sources/bcs.move
index 8bb574f327..a7d4c19082 100644
--- a/moveos/moveos-stdlib/moveos-stdlib/sources/bcs.move
+++ b/moveos/moveos-stdlib/moveos-stdlib/sources/bcs.move
@@ -9,6 +9,9 @@
 /// a general conversion back-and-force is needed, consider the `moveos_std::Any` type which preserves invariants.
 module moveos_std::bcs{
 
+    /// The request Move type is not match with input Move type.
+    const ErrorTypeNotMatch: u64 = 1;
+    
     public fun to_bytes<MoveValue>(v: &MoveValue): vector<u8>{
         std::bcs::to_bytes(v)
     }
diff --git a/moveos/moveos-stdlib/moveos-stdlib/sources/move_module.move b/moveos/moveos-stdlib/moveos-stdlib/sources/move_module.move
index 8f3a5a7523..f540e23126 100644
--- a/moveos/moveos-stdlib/moveos-stdlib/sources/move_module.move
+++ b/moveos/moveos-stdlib/moveos-stdlib/sources/move_module.move
@@ -8,6 +8,15 @@ module moveos_std::move_module {
 
     friend moveos_std::account_storage;
     
+    /// Module address is not the same as the signer
+    const ErrorAddressNotMatchWithSigner: u64 = 1;
+
+    /// Module verification error
+    const ErrorModuleVerificationError: u64 = 2;
+
+    /// Module incompatible with the old ones.
+    const ErrorModuleIncompatible: u64 = 3;
+
     struct MoveModule has store, drop {
         byte_codes: vector<u8>,
     }
@@ -22,12 +31,13 @@ module moveos_std::move_module {
         module_name_inner(&move_module.byte_codes)
     }
 
-    /// Verify the modules and return their names and names of the modules with init function.
+    /// Sort modules by dependency order and then verify. 
+    /// Return their names and names of the modules with init function if sorted dependency order.
     /// This function will ensure the module's bytecode is valid and the module id is matching the account address.
     /// Return
-    ///     The first vector is the module names of all the modules.
-    ///     The second vector is the module names of the modules with init function.
-    public fun verify_modules(modules: &vector<MoveModule>, account_address: address): (vector<String>, vector<String>) {
+    ///     1. Module names of all the modules. Order of names is not matching the input, but sorted by module dependency order
+    ///     2. Module names of the modules with init function.
+    public fun sort_and_verify_modules(modules: &vector<MoveModule>, account_address: address): (vector<String>, vector<String>) {
         let bytes_vec = vector::empty<vector<u8>>();
         let i = 0u64;
         let len = vector::length(modules);
@@ -35,7 +45,7 @@ module moveos_std::move_module {
             vector::push_back(&mut bytes_vec, vector::borrow(modules, i).byte_codes);
             i = i + 1;
         };
-        verify_modules_inner(bytes_vec, account_address)
+        sort_and_verify_modules_inner(bytes_vec, account_address)
     }
 
     /// Check module compatibility when upgrading
@@ -46,12 +56,9 @@ module moveos_std::move_module {
 
     native fun module_name_inner(byte_codes: &vector<u8>): String;
 
-    /// Native function that verifies the modules and returns their names and 
-    /// names of the modules with init function
-    /// Return
-    ///     The first vector is the module names of all the modules.
-    ///     The second vector is the module names of the modules with init function.
-    native fun verify_modules_inner(modules: vector<vector<u8>>, account_address: address): (vector<String>, vector<String>);
+    /// Sort modules by dependency order and then verify. 
+    /// Return their names and names of the modules with init function if sorted dependency order.
+    native fun sort_and_verify_modules_inner(modules: vector<vector<u8>>, account_address: address): (vector<String>, vector<String>);
     
     /// Request to call the init functions of the given modules
     /// module_names: names of modules which have a init function
diff --git a/moveos/moveos-stdlib/moveos-stdlib/sources/raw_table.move b/moveos/moveos-stdlib/moveos-stdlib/sources/raw_table.move
index c0d4f59c7d..b78552c814 100644
--- a/moveos/moveos-stdlib/moveos-stdlib/sources/raw_table.move
+++ b/moveos/moveos-stdlib/moveos-stdlib/sources/raw_table.move
@@ -19,8 +19,10 @@ module moveos_std::raw_table {
     const ErrorAlreadyExists: u64 = 1;
     /// Can not found the key in the table
     const ErrorNotFound: u64 = 2;
+    /// Duplicate operation on the table
+    const ErrorDuplicateOperation: u64 = 3;
     /// The table is not empty
-    const ErrorNotEmpty: u64 = 3;
+    const ErrorNotEmpty: u64 = 4;
 
      //TODO redesign the global object storage handle
     const GlobalObjectStorageHandle: address = @0x0;
diff --git a/moveos/moveos-stdlib/src/natives/moveos_stdlib/bcs.rs b/moveos/moveos-stdlib/src/natives/moveos_stdlib/bcs.rs
index 1bbd7b3081..639dc40335 100644
--- a/moveos/moveos-stdlib/src/natives/moveos_stdlib/bcs.rs
+++ b/moveos/moveos-stdlib/src/natives/moveos_stdlib/bcs.rs
@@ -12,6 +12,8 @@ use move_vm_types::{
 use smallvec::smallvec;
 use std::collections::VecDeque;
 
+const E_TYPE_NOT_MATCH: u64 = 1;
+
 #[derive(Debug, Clone)]
 pub struct FromBytesGasParameters {
     pub base: InternalGas,
@@ -27,7 +29,7 @@ impl FromBytesGasParameters {
 /// Bytes are in BCS (Binary Canonical Serialization) format.
 #[inline]
 fn native_from_bytes(
-    _gas_params: &FromBytesGasParameters,
+    gas_params: &FromBytesGasParameters,
     context: &mut NativeContext,
     ty_args: Vec<Type>,
     mut args: VecDeque<Value>,
@@ -35,7 +37,7 @@ fn native_from_bytes(
     debug_assert_eq!(ty_args.len(), 1);
     debug_assert_eq!(args.len(), 1);
 
-    let cost = 0.into();
+    let cost = gas_params.base;
 
     // TODO(Gas): charge for getting the layout
     let layout = context.type_to_type_layout(&ty_args[0])?.ok_or_else(|| {
@@ -49,8 +51,10 @@ fn native_from_bytes(
     let val = match Value::simple_deserialize(&bytes, &layout) {
         Some(val) => val,
         None => {
-            // TODO(gas): charge the gas for the failure.
-            return Err(PartialVMError::new(StatusCode::VALUE_DESERIALIZATION_ERROR));
+            return Ok(NativeResult::err(
+                cost,
+                moveos_types::move_std::error::invalid_argument(E_TYPE_NOT_MATCH),
+            ));
         }
     };
     // TODO(gas): charge gas for deserialization
diff --git a/moveos/moveos-stdlib/src/natives/moveos_stdlib/move_module.rs b/moveos/moveos-stdlib/src/natives/moveos_stdlib/move_module.rs
index de476ca4a9..44a733af5c 100644
--- a/moveos/moveos-stdlib/src/natives/moveos_stdlib/move_module.rs
+++ b/moveos/moveos-stdlib/src/natives/moveos_stdlib/move_module.rs
@@ -23,11 +23,16 @@ use move_vm_types::{
     pop_arg,
     values::{Struct, Value, Vector, VectorRef},
 };
+use moveos_stdlib_builder::dependency_order::sort_by_dependency_order;
 use smallvec::smallvec;
 use std::collections::{BTreeSet, VecDeque};
 
 // ========================================================================================
 
+const E_ADDRESS_NOT_MATCH_WITH_SIGNER: u64 = 1;
+const E_MODULE_VERIFICATION_ERROR: u64 = 2;
+const E_MODULE_INCOMPATIBLE: u64 = 3;
+
 /// The native module context.
 #[derive(Tid)]
 pub struct NativeModuleContext<'a> {
@@ -68,7 +73,6 @@ fn native_module_name_inner(
     let name = module.self_id().name().to_owned().into_string();
     let cost = gas_params.base
         + if gas_params.per_byte_in_str > 0.into() {
-            //TODO charge gas cost
             gas_params.per_byte_in_str * NumBytes::new(name.len() as u64)
         } else {
             0.into()
@@ -79,7 +83,7 @@ fn native_module_name_inner(
 }
 
 /***************************************************************************************************
- * native fun verify_modules_inner(
+ * native fun sort_and_verify_modules_inner(
  *      modules: &vector<vector<u8>>,
  *      account_address: address
  * ): (vector<String>, vector<String>);
@@ -94,7 +98,7 @@ pub struct VerifyModulesGasParameters {
     pub per_byte: InternalGasPerByte,
 }
 
-fn native_verify_modules_inner(
+fn native_sort_and_verify_modules_inner(
     gas_params: &VerifyModulesGasParameters,
     context: &mut NativeContext,
     _ty_args: Vec<Type>,
@@ -112,7 +116,9 @@ fn native_verify_modules_inner(
         .iter()
         .map(|b| CompiledModule::deserialize(b))
         .collect::<PartialVMResult<Vec<CompiledModule>>>()?;
-
+    let compiled_modules = sort_by_dependency_order(&compiled_modules).map_err(|e| {
+        PartialVMError::new(StatusCode::CYCLIC_MODULE_DEPENDENCY).with_message(e.to_string())
+    })?;
     // move verifier
     context.verify_module_bundle_for_publication(&compiled_modules)?;
 
@@ -122,13 +128,10 @@ fn native_verify_modules_inner(
     let mut init_identifier = vec![];
     for module in &compiled_modules {
         if *module.self_id().address() != account_address {
-            return Err(
-                PartialVMError::new(StatusCode::VERIFICATION_ERROR).with_message(format!(
-                    "Module address {:?} not match with signer address {:?}",
-                    module.self_id().address(),
-                    account_address
-                )),
-            );
+            return Ok(NativeResult::err(
+                cost,
+                moveos_types::move_std::error::invalid_argument(E_ADDRESS_NOT_MATCH_WITH_SIGNER),
+            ));
         }
         let result = moveos_verifier::verifier::verify_module(module, module_context.resolver);
         match result {
@@ -138,7 +141,12 @@ fn native_verify_modules_inner(
                 }
                 module_names.push(module.self_id().name().to_owned().into_string());
             }
-            Err(_) => return Err(PartialVMError::new(StatusCode::VERIFICATION_ERROR)),
+            Err(_) => {
+                return Ok(NativeResult::err(
+                    cost,
+                    moveos_types::move_std::error::invalid_argument(E_MODULE_VERIFICATION_ERROR),
+                ))
+            }
         }
     }
 
@@ -245,7 +253,15 @@ fn check_compatibililty_inner(
         let new_m = normalized::Module::new(&new_module);
         let old_m = normalized::Module::new(&old_module);
 
-        compat.check(&old_m, &new_m)?;
+        match compat.check(&old_m, &new_m) {
+            Ok(_) => {}
+            Err(_) => {
+                return Ok(NativeResult::err(
+                    cost,
+                    moveos_types::move_std::error::invalid_argument(E_MODULE_INCOMPATIBLE),
+                ))
+            }
+        }
     }
     Ok(NativeResult::ok(cost, smallvec![]))
 }
@@ -256,7 +272,7 @@ fn check_compatibililty_inner(
 #[derive(Debug, Clone)]
 pub struct GasParameters {
     pub module_name_inner: ModuleNameInnerGasParameters,
-    pub verify_modules_inner: VerifyModulesGasParameters,
+    pub sort_and_verify_modules_inner: VerifyModulesGasParameters,
     pub request_init_functions: RequestInitFunctionsGasParameters,
     pub check_compatibililty_inner: CheckCompatibilityInnerGasParameters,
 }
@@ -268,7 +284,7 @@ impl GasParameters {
                 base: 0.into(),
                 per_byte_in_str: 0.into(),
             },
-            verify_modules_inner: VerifyModulesGasParameters {
+            sort_and_verify_modules_inner: VerifyModulesGasParameters {
                 base: 0.into(),
                 per_byte: 0.into(),
             },
@@ -291,8 +307,11 @@ pub fn make_all(gas_params: GasParameters) -> impl Iterator<Item = (String, Nati
             make_native(gas_params.module_name_inner, native_module_name_inner),
         ),
         (
-            "verify_modules_inner",
-            make_native(gas_params.verify_modules_inner, native_verify_modules_inner),
+            "sort_and_verify_modules_inner",
+            make_native(
+                gas_params.sort_and_verify_modules_inner,
+                native_sort_and_verify_modules_inner,
+            ),
         ),
         (
             "request_init_functions",
diff --git a/moveos/moveos-stdlib/src/natives/moveos_stdlib/raw_table/mod.rs b/moveos/moveos-stdlib/src/natives/moveos_stdlib/raw_table/mod.rs
index ad2a697e67..86408772e3 100644
--- a/moveos/moveos-stdlib/src/natives/moveos_stdlib/raw_table/mod.rs
+++ b/moveos/moveos-stdlib/src/natives/moveos_stdlib/raw_table/mod.rs
@@ -52,6 +52,7 @@ pub struct NativeTableContext<'a> {
 const E_ALREADY_EXISTS: u64 = 1;
 const E_NOT_FOUND: u64 = 2;
 const E_DUPLICATE_OPERATION: u64 = 3;
+const _E_NOT_EMPTY: u64 = 4; // This is not used, just used to keep consistent with raw_table.move
 
 // ===========================================================================================
 // Private Data Structures and Constants