diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
index e66c4f27fbe88c26c35792cab8d8e5f5ddb2f0ea..2206aea78ec262bc0ea174c39892439f2414659e 100644
--- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
@@ -45,10 +45,7 @@ use frame_support::{
 	ord_parameter_types, parameter_types,
 	traits::{
 		fungible, fungibles,
-		tokens::{
-			imbalance::ResolveAssetTo, nonfungibles_v2::Inspect, Fortitude::Polite,
-			Preservation::Expendable,
-		},
+		tokens::{imbalance::ResolveAssetTo, nonfungibles_v2::Inspect},
 		AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, InstanceFilter,
 		Nothing, TransformOrigin,
 	},
@@ -68,7 +65,7 @@ use parachains_common::{
 	NORMAL_DISPATCH_RATIO,
 };
 use sp_api::impl_runtime_apis;
-use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H160};
+use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H160, U256};
 use sp_runtime::{
 	generic, impl_opaque_keys,
 	traits::{AccountIdConversion, BlakeTwo256, Block as BlockT, Saturating, Verify},
@@ -127,7 +124,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
 	spec_name: alloc::borrow::Cow::Borrowed("westmint"),
 	impl_name: alloc::borrow::Cow::Borrowed("westmint"),
 	authoring_version: 1,
-	spec_version: 1_016_005,
+	spec_version: 1_016_006,
 	impl_version: 0,
 	apis: RUNTIME_API_VERSIONS,
 	transaction_version: 16,
@@ -2080,10 +2077,8 @@ impl_runtime_apis! {
 
 	impl pallet_revive::ReviveApi<Block, AccountId, Balance, Nonce, BlockNumber, EventRecord> for Runtime
 	{
-		fn balance(address: H160) -> Balance {
-			use frame_support::traits::fungible::Inspect;
-			let account = <Runtime as pallet_revive::Config>::AddressMapper::to_account_id(&address);
-			Balances::reducible_balance(&account, Expendable, Polite)
+		fn balance(address: H160) -> U256 {
+			Revive::evm_balance(&address)
 		}
 
 		fn nonce(address: H160) -> Nonce {
@@ -2093,7 +2088,7 @@ impl_runtime_apis! {
 		fn eth_transact(
 			from: H160,
 			dest: Option<H160>,
-			value: Balance,
+			value: U256,
 			input: Vec<u8>,
 			gas_limit: Option<Weight>,
 			storage_deposit_limit: Option<Balance>,
diff --git a/prdoc/pr_6466.prdoc b/prdoc/pr_6466.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..0faa6afc800541e01817d6856dd05625e9dd4966
--- /dev/null
+++ b/prdoc/pr_6466.prdoc
@@ -0,0 +1,12 @@
+title: '[pallet-revive] add piggy-bank sol example'
+doc:
+- audience: Runtime Dev
+  description: |-
+    This PR update the pallet to use the EVM 18 decimal balance in contracts call and host functions instead of the native balance.
+
+    It also updates the js example to add the piggy-bank solidity contract that expose the problem
+crates:
+- name: pallet-revive-eth-rpc
+  bump: minor
+- name: pallet-revive
+  bump: minor
diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs
index 5a2ff3ceb7f6aad0f402bf987e606eca28987d07..914b51fb5621dc262b574fe2c03c87cc98e2ccb1 100644
--- a/substrate/bin/node/runtime/src/lib.rs
+++ b/substrate/bin/node/runtime/src/lib.rs
@@ -54,7 +54,7 @@ use frame_support::{
 		},
 		tokens::{
 			imbalance::ResolveAssetTo, nonfungibles_v2::Inspect, pay::PayAssetFromAccount,
-			Fortitude::Polite, GetSalary, PayFromAccount, Preservation::Preserve,
+			GetSalary, PayFromAccount,
 		},
 		AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, Contains,
 		Currency, EitherOfDiverse, EnsureOriginWithArg, EqualPrivilegeOnly, Imbalance, InsideBoth,
@@ -86,6 +86,7 @@ use pallet_nis::WithMaximumOf;
 use pallet_nomination_pools::PoolId;
 use pallet_revive::{evm::runtime::EthExtra, AddressMapper};
 use pallet_session::historical as pallet_session_historical;
+use sp_core::U256;
 // Can't use `FungibleAdapter` here until Treasury pallet migrates to fungibles
 // <https://github.com/paritytech/polkadot-sdk/issues/226>
 use pallet_broker::TaskId;
@@ -3205,10 +3206,8 @@ impl_runtime_apis! {
 
 	impl pallet_revive::ReviveApi<Block, AccountId, Balance, Nonce, BlockNumber, EventRecord> for Runtime
 	{
-		fn balance(address: H160) -> Balance {
-			use frame_support::traits::fungible::Inspect;
-			let account = <Runtime as pallet_revive::Config>::AddressMapper::to_account_id(&address);
-			Balances::reducible_balance(&account, Preserve, Polite)
+		fn balance(address: H160) -> U256 {
+			Revive::evm_balance(&address)
 		}
 
 		fn nonce(address: H160) -> Nonce {
@@ -3219,7 +3218,7 @@ impl_runtime_apis! {
 		fn eth_transact(
 			from: H160,
 			dest: Option<H160>,
-			value: Balance,
+			value: U256,
 			input: Vec<u8>,
 			gas_limit: Option<Weight>,
 			storage_deposit_limit: Option<Balance>,
diff --git a/substrate/frame/revive/rpc/examples/js/abi/event.json b/substrate/frame/revive/rpc/examples/js/abi/event.json
new file mode 100644
index 0000000000000000000000000000000000000000..d36089fbc84ea25fc4cfcc757222526aaa14f1fb
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/abi/event.json
@@ -0,0 +1,34 @@
+[
+	{
+		"anonymous": false,
+		"inputs": [
+			{
+				"indexed": true,
+				"internalType": "address",
+				"name": "sender",
+				"type": "address"
+			},
+			{
+				"indexed": false,
+				"internalType": "uint256",
+				"name": "value",
+				"type": "uint256"
+			},
+			{
+				"indexed": false,
+				"internalType": "string",
+				"name": "message",
+				"type": "string"
+			}
+		],
+		"name": "ExampleEvent",
+		"type": "event"
+	},
+	{
+		"inputs": [],
+		"name": "triggerEvent",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	}
+]
diff --git a/substrate/frame/revive/rpc/examples/js/abi/piggyBank.json b/substrate/frame/revive/rpc/examples/js/abi/piggyBank.json
new file mode 100644
index 0000000000000000000000000000000000000000..2c2cfd5f753377371f4fb6d111fda23aabf863e7
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/abi/piggyBank.json
@@ -0,0 +1,65 @@
+[
+	{
+		"inputs": [],
+		"stateMutability": "nonpayable",
+		"type": "constructor"
+	},
+	{
+		"inputs": [],
+		"name": "deposit",
+		"outputs": [
+			{
+				"internalType": "uint256",
+				"name": "",
+				"type": "uint256"
+			}
+		],
+		"stateMutability": "payable",
+		"type": "function"
+	},
+	{
+		"inputs": [],
+		"name": "getDeposit",
+		"outputs": [
+			{
+				"internalType": "uint256",
+				"name": "",
+				"type": "uint256"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [],
+		"name": "owner",
+		"outputs": [
+			{
+				"internalType": "address",
+				"name": "",
+				"type": "address"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "uint256",
+				"name": "withdrawAmount",
+				"type": "uint256"
+			}
+		],
+		"name": "withdraw",
+		"outputs": [
+			{
+				"internalType": "uint256",
+				"name": "remainingBal",
+				"type": "uint256"
+			}
+		],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	}
+]
diff --git a/substrate/frame/revive/rpc/examples/js/abi/revert.json b/substrate/frame/revive/rpc/examples/js/abi/revert.json
new file mode 100644
index 0000000000000000000000000000000000000000..be2945fcc0a59e28ea15ce24bb25badad71cd993
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/abi/revert.json
@@ -0,0 +1,14 @@
+[
+	{
+		"inputs": [],
+		"stateMutability": "nonpayable",
+		"type": "constructor"
+	},
+	{
+		"inputs": [],
+		"name": "doRevert",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	}
+]
diff --git a/substrate/frame/revive/rpc/examples/js/bun.lockb b/substrate/frame/revive/rpc/examples/js/bun.lockb
index 8bf47d7eb8b82734467165627413c33adede6fd6..700dca51da2ad3f843e890258b59c16fd4df6457 100755
Binary files a/substrate/frame/revive/rpc/examples/js/bun.lockb and b/substrate/frame/revive/rpc/examples/js/bun.lockb differ
diff --git a/substrate/frame/revive/rpc/examples/js/contracts/PiggyBank.sol b/substrate/frame/revive/rpc/examples/js/contracts/PiggyBank.sol
new file mode 100644
index 0000000000000000000000000000000000000000..1906c46588895567b7edb8cd48a459b39cd2dd22
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/contracts/PiggyBank.sol
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+contract PiggyBank {
+
+    uint private balance;
+    address public owner;
+
+    constructor() {
+        owner = msg.sender;
+        balance = 0;
+    }
+
+    function deposit() public payable returns (uint) {
+        balance += msg.value;
+        return balance;
+    }
+
+    function getDeposit() public view returns (uint) {
+        return balance;
+    }
+
+    function withdraw(uint withdrawAmount) public returns (uint remainingBal) {
+        require(msg.sender == owner);
+        balance -= withdrawAmount;
+        (bool success, ) = payable(msg.sender).call{value: withdrawAmount}("");
+        require(success, "Transfer failed");
+
+        return balance;
+    }
+}
+
diff --git a/substrate/frame/revive/rpc/examples/js/evm-contracts.json b/substrate/frame/revive/rpc/examples/js/evm-contracts.json
deleted file mode 100644
index 4d98f5dd8149266c206f3406831446764e686151..0000000000000000000000000000000000000000
--- a/substrate/frame/revive/rpc/examples/js/evm-contracts.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
-  "event": {
-    "abi": [
-      {
-        "anonymous": false,
-        "inputs": [
-          {
-            "indexed": true,
-            "internalType": "address",
-            "name": "sender",
-            "type": "address"
-          },
-          {
-            "indexed": false,
-            "internalType": "uint256",
-            "name": "value",
-            "type": "uint256"
-          },
-          {
-            "indexed": false,
-            "internalType": "string",
-            "name": "message",
-            "type": "string"
-          }
-        ],
-        "name": "ExampleEvent",
-        "type": "event"
-      },
-      {
-        "inputs": [],
-        "name": "triggerEvent",
-        "outputs": [],
-        "stateMutability": "nonpayable",
-        "type": "function"
-      }
-    ],
-    "bytecode": "6080604052348015600e575f5ffd5b506101b68061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063ede48fb71461002d575b5f5ffd5b610035610037565b005b5f61303990505f6040518060400160405280600b81526020017f48656c6c6f20776f726c6400000000000000000000000000000000000000000081525090503373ffffffffffffffffffffffffffffffffffffffff167f1585375487296ff2f0370daeec4214074a032b31af827c12622fa9a58c16c7d083836040516100be929190610152565b60405180910390a25050565b5f819050919050565b6100dc816100ca565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f610124826100e2565b61012e81856100ec565b935061013e8185602086016100fc565b6101478161010a565b840191505092915050565b5f6040820190506101655f8301856100d3565b8181036020830152610177818461011a565b9050939250505056fea2646970667358221220a159f2cdba512e018377f5822cfd8ef04769755d98c3e494275605d96d7d13e864736f6c634300081c0033"
-  },
-  "revert": {
-    "abi": [
-      {
-        "inputs": [],
-        "stateMutability": "nonpayable",
-        "type": "constructor"
-      },
-      {
-        "inputs": [],
-        "name": "doRevert",
-        "outputs": [],
-        "stateMutability": "nonpayable",
-        "type": "function"
-      }
-    ],
-    "bytecode": "6080604052348015600e575f5ffd5b506101138061001c5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c8063afc874d214602a575b5f5ffd5b60306032565b005b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160629060c1565b60405180910390fd5b5f82825260208201905092915050565b7f726576657274206d6573736167650000000000000000000000000000000000005f82015250565b5f60ad600e83606b565b915060b682607b565b602082019050919050565b5f6020820190508181035f83015260d68160a3565b905091905056fea264697066735822122084f7096e030faf779d12b20184187708d335e4bcd4208a52c0651700fe8dde6a64736f6c634300081c0033"
-  }
-}
\ No newline at end of file
diff --git a/substrate/frame/revive/rpc/examples/js/index.html b/substrate/frame/revive/rpc/examples/js/index.html
index 052daf2787f657855a889e1134300bd8feabb154..97efebe180ea1dc8c1d79cb99712ce9751142539 100644
--- a/substrate/frame/revive/rpc/examples/js/index.html
+++ b/substrate/frame/revive/rpc/examples/js/index.html
@@ -1,29 +1,38 @@
 <!doctype html>
 <html lang="en">
-  <head>
-    <meta charset="UTF-8" />
-    <link rel="icon" href="https://polkadot.com/favicon.ico">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>MetaMask Playground</title>
-    <style>
-	  input { width: 300px; margin-right: 10px; }
+	<head>
+		<meta charset="UTF-8" />
+		<link rel="icon" href="https://polkadot.com/favicon.ico" />
+		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+		<title>MetaMask Playground</title>
+		<style>
+			input {
+				width: 300px;
+				margin-right: 10px;
+			}
 
-      button {
-        display: block;
-        margin-bottom: 10px;
-      }
-    </style>
-  </head>
-  <body>
-    <input id="transferInput" type="text" style="float: left" placeholder="Destination address" value="0x3cd0a705a2dc65e5b1e1205896baa2be8a07c6e0" />
-    <button id="transferButton">Transfer coins</button>
+			button {
+				display: block;
+				margin-bottom: 10px;
+			}
+		</style>
+	</head>
+	<body>
+		<input
+			id="transferInput"
+			type="text"
+			style="float: left"
+			placeholder="Destination address"
+			value="0x3cd0a705a2dc65e5b1e1205896baa2be8a07c6e0"
+		/>
+		<button id="transferButton">Transfer coins</button>
 
-    <button id="deployButton">Deploy Contract</button>
+		<button id="deployButton">Deploy Contract</button>
 
-    <input id="callInput" type="text" style="float: left" placeholder="Contract address" />
-    <button id="callButton">Call Contract</button>
+		<input id="callInput" type="text" style="float: left" placeholder="Contract address" />
+		<button id="callButton">Call Contract</button>
 
-    <button id="deployAndCallButton">Deploy and Call Contract</button>
-    <script type="module" src="src/web.ts"></script>
-  </body>
+		<button id="deployAndCallButton">Deploy and Call Contract</button>
+		<script type="module" src="src/web.ts"></script>
+	</body>
 </html>
diff --git a/substrate/frame/revive/rpc/examples/js/package-lock.json b/substrate/frame/revive/rpc/examples/js/package-lock.json
index f1453eae64cce48803599b69bc6e0b837443c640..5c7db0abc936464077ed01a147472fe662729671 100644
--- a/substrate/frame/revive/rpc/examples/js/package-lock.json
+++ b/substrate/frame/revive/rpc/examples/js/package-lock.json
@@ -1,443 +1,443 @@
 {
-  "name": "demo",
-  "version": "0.0.0",
-  "lockfileVersion": 3,
-  "requires": true,
-  "packages": {
-    "": {
-      "name": "demo",
-      "version": "0.0.0",
-      "dependencies": {
-        "ethers": "^6.13.1",
-        "solc": "^0.8.28"
-      },
-      "devDependencies": {
-        "typescript": "^5.5.3",
-        "vite": "^5.4.8"
-      }
-    },
-    "node_modules/@adraffy/ens-normalize": {
-      "version": "1.10.1",
-      "license": "MIT"
-    },
-    "node_modules/@esbuild/linux-x64": {
-      "version": "0.21.5",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@noble/curves": {
-      "version": "1.2.0",
-      "license": "MIT",
-      "dependencies": {
-        "@noble/hashes": "1.3.2"
-      },
-      "funding": {
-        "url": "https://paulmillr.com/funding/"
-      }
-    },
-    "node_modules/@noble/hashes": {
-      "version": "1.3.2",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 16"
-      },
-      "funding": {
-        "url": "https://paulmillr.com/funding/"
-      }
-    },
-    "node_modules/@rollup/rollup-linux-x64-gnu": {
-      "version": "4.24.0",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ]
-    },
-    "node_modules/@rollup/rollup-linux-x64-musl": {
-      "version": "4.24.0",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ]
-    },
-    "node_modules/@types/estree": {
-      "version": "1.0.6",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/@types/node": {
-      "version": "18.15.13",
-      "license": "MIT"
-    },
-    "node_modules/aes-js": {
-      "version": "4.0.0-beta.5",
-      "license": "MIT"
-    },
-    "node_modules/command-exists": {
-      "version": "1.2.9",
-      "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz",
-      "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==",
-      "license": "MIT"
-    },
-    "node_modules/commander": {
-      "version": "8.3.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
-      "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 12"
-      }
-    },
-    "node_modules/esbuild": {
-      "version": "0.21.5",
-      "dev": true,
-      "hasInstallScript": true,
-      "license": "MIT",
-      "bin": {
-        "esbuild": "bin/esbuild"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "optionalDependencies": {
-        "@esbuild/aix-ppc64": "0.21.5",
-        "@esbuild/android-arm": "0.21.5",
-        "@esbuild/android-arm64": "0.21.5",
-        "@esbuild/android-x64": "0.21.5",
-        "@esbuild/darwin-arm64": "0.21.5",
-        "@esbuild/darwin-x64": "0.21.5",
-        "@esbuild/freebsd-arm64": "0.21.5",
-        "@esbuild/freebsd-x64": "0.21.5",
-        "@esbuild/linux-arm": "0.21.5",
-        "@esbuild/linux-arm64": "0.21.5",
-        "@esbuild/linux-ia32": "0.21.5",
-        "@esbuild/linux-loong64": "0.21.5",
-        "@esbuild/linux-mips64el": "0.21.5",
-        "@esbuild/linux-ppc64": "0.21.5",
-        "@esbuild/linux-riscv64": "0.21.5",
-        "@esbuild/linux-s390x": "0.21.5",
-        "@esbuild/linux-x64": "0.21.5",
-        "@esbuild/netbsd-x64": "0.21.5",
-        "@esbuild/openbsd-x64": "0.21.5",
-        "@esbuild/sunos-x64": "0.21.5",
-        "@esbuild/win32-arm64": "0.21.5",
-        "@esbuild/win32-ia32": "0.21.5",
-        "@esbuild/win32-x64": "0.21.5"
-      }
-    },
-    "node_modules/ethers": {
-      "version": "6.13.3",
-      "funding": [
-        {
-          "type": "individual",
-          "url": "https://github.com/sponsors/ethers-io/"
-        },
-        {
-          "type": "individual",
-          "url": "https://www.buymeacoffee.com/ricmoo"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "@adraffy/ens-normalize": "1.10.1",
-        "@noble/curves": "1.2.0",
-        "@noble/hashes": "1.3.2",
-        "@types/node": "18.15.13",
-        "aes-js": "4.0.0-beta.5",
-        "tslib": "2.4.0",
-        "ws": "8.17.1"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/follow-redirects": {
-      "version": "1.15.9",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
-      "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
-      "funding": [
-        {
-          "type": "individual",
-          "url": "https://github.com/sponsors/RubenVerborgh"
-        }
-      ],
-      "license": "MIT",
-      "engines": {
-        "node": ">=4.0"
-      },
-      "peerDependenciesMeta": {
-        "debug": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/js-sha3": {
-      "version": "0.8.0",
-      "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
-      "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==",
-      "license": "MIT"
-    },
-    "node_modules/memorystream": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
-      "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
-      "engines": {
-        "node": ">= 0.10.0"
-      }
-    },
-    "node_modules/nanoid": {
-      "version": "3.3.7",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "MIT",
-      "bin": {
-        "nanoid": "bin/nanoid.cjs"
-      },
-      "engines": {
-        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
-      }
-    },
-    "node_modules/os-tmpdir": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-      "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/picocolors": {
-      "version": "1.1.0",
-      "dev": true,
-      "license": "ISC"
-    },
-    "node_modules/postcss": {
-      "version": "8.4.47",
-      "dev": true,
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/postcss/"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/postcss"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "nanoid": "^3.3.7",
-        "picocolors": "^1.1.0",
-        "source-map-js": "^1.2.1"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14"
-      }
-    },
-    "node_modules/rollup": {
-      "version": "4.24.0",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@types/estree": "1.0.6"
-      },
-      "bin": {
-        "rollup": "dist/bin/rollup"
-      },
-      "engines": {
-        "node": ">=18.0.0",
-        "npm": ">=8.0.0"
-      },
-      "optionalDependencies": {
-        "@rollup/rollup-android-arm-eabi": "4.24.0",
-        "@rollup/rollup-android-arm64": "4.24.0",
-        "@rollup/rollup-darwin-arm64": "4.24.0",
-        "@rollup/rollup-darwin-x64": "4.24.0",
-        "@rollup/rollup-linux-arm-gnueabihf": "4.24.0",
-        "@rollup/rollup-linux-arm-musleabihf": "4.24.0",
-        "@rollup/rollup-linux-arm64-gnu": "4.24.0",
-        "@rollup/rollup-linux-arm64-musl": "4.24.0",
-        "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0",
-        "@rollup/rollup-linux-riscv64-gnu": "4.24.0",
-        "@rollup/rollup-linux-s390x-gnu": "4.24.0",
-        "@rollup/rollup-linux-x64-gnu": "4.24.0",
-        "@rollup/rollup-linux-x64-musl": "4.24.0",
-        "@rollup/rollup-win32-arm64-msvc": "4.24.0",
-        "@rollup/rollup-win32-ia32-msvc": "4.24.0",
-        "@rollup/rollup-win32-x64-msvc": "4.24.0",
-        "fsevents": "~2.3.2"
-      }
-    },
-    "node_modules/semver": {
-      "version": "5.7.2",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
-      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
-      "license": "ISC",
-      "bin": {
-        "semver": "bin/semver"
-      }
-    },
-    "node_modules/solc": {
-      "version": "0.8.28",
-      "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.28.tgz",
-      "integrity": "sha512-AFCiJ+b4RosyyNhnfdVH4ZR1+TxiL91iluPjw0EJslIu4LXGM9NYqi2z5y8TqochC4tcH9QsHfwWhOIC9jPDKA==",
-      "license": "MIT",
-      "dependencies": {
-        "command-exists": "^1.2.8",
-        "commander": "^8.1.0",
-        "follow-redirects": "^1.12.1",
-        "js-sha3": "0.8.0",
-        "memorystream": "^0.3.1",
-        "semver": "^5.5.0",
-        "tmp": "0.0.33"
-      },
-      "bin": {
-        "solcjs": "solc.js"
-      },
-      "engines": {
-        "node": ">=10.0.0"
-      }
-    },
-    "node_modules/source-map-js": {
-      "version": "1.2.1",
-      "dev": true,
-      "license": "BSD-3-Clause",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/tmp": {
-      "version": "0.0.33",
-      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
-      "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
-      "license": "MIT",
-      "dependencies": {
-        "os-tmpdir": "~1.0.2"
-      },
-      "engines": {
-        "node": ">=0.6.0"
-      }
-    },
-    "node_modules/tslib": {
-      "version": "2.4.0",
-      "license": "0BSD"
-    },
-    "node_modules/typescript": {
-      "version": "5.6.3",
-      "dev": true,
-      "license": "Apache-2.0",
-      "bin": {
-        "tsc": "bin/tsc",
-        "tsserver": "bin/tsserver"
-      },
-      "engines": {
-        "node": ">=14.17"
-      }
-    },
-    "node_modules/vite": {
-      "version": "5.4.8",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "esbuild": "^0.21.3",
-        "postcss": "^8.4.43",
-        "rollup": "^4.20.0"
-      },
-      "bin": {
-        "vite": "bin/vite.js"
-      },
-      "engines": {
-        "node": "^18.0.0 || >=20.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/vitejs/vite?sponsor=1"
-      },
-      "optionalDependencies": {
-        "fsevents": "~2.3.3"
-      },
-      "peerDependencies": {
-        "@types/node": "^18.0.0 || >=20.0.0",
-        "less": "*",
-        "lightningcss": "^1.21.0",
-        "sass": "*",
-        "sass-embedded": "*",
-        "stylus": "*",
-        "sugarss": "*",
-        "terser": "^5.4.0"
-      },
-      "peerDependenciesMeta": {
-        "@types/node": {
-          "optional": true
-        },
-        "less": {
-          "optional": true
-        },
-        "lightningcss": {
-          "optional": true
-        },
-        "sass": {
-          "optional": true
-        },
-        "sass-embedded": {
-          "optional": true
-        },
-        "stylus": {
-          "optional": true
-        },
-        "sugarss": {
-          "optional": true
-        },
-        "terser": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/ws": {
-      "version": "8.17.1",
-      "license": "MIT",
-      "engines": {
-        "node": ">=10.0.0"
-      },
-      "peerDependencies": {
-        "bufferutil": "^4.0.1",
-        "utf-8-validate": ">=5.0.2"
-      },
-      "peerDependenciesMeta": {
-        "bufferutil": {
-          "optional": true
-        },
-        "utf-8-validate": {
-          "optional": true
-        }
-      }
-    }
-  }
+	"name": "demo",
+	"version": "0.0.0",
+	"lockfileVersion": 3,
+	"requires": true,
+	"packages": {
+		"": {
+			"name": "demo",
+			"version": "0.0.0",
+			"dependencies": {
+				"ethers": "^6.13.1",
+				"solc": "^0.8.28"
+			},
+			"devDependencies": {
+				"typescript": "^5.5.3",
+				"vite": "^5.4.8"
+			}
+		},
+		"node_modules/@adraffy/ens-normalize": {
+			"version": "1.10.1",
+			"license": "MIT"
+		},
+		"node_modules/@esbuild/linux-x64": {
+			"version": "0.21.5",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"license": "MIT",
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@noble/curves": {
+			"version": "1.2.0",
+			"license": "MIT",
+			"dependencies": {
+				"@noble/hashes": "1.3.2"
+			},
+			"funding": {
+				"url": "https://paulmillr.com/funding/"
+			}
+		},
+		"node_modules/@noble/hashes": {
+			"version": "1.3.2",
+			"license": "MIT",
+			"engines": {
+				"node": ">= 16"
+			},
+			"funding": {
+				"url": "https://paulmillr.com/funding/"
+			}
+		},
+		"node_modules/@rollup/rollup-linux-x64-gnu": {
+			"version": "4.24.0",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"license": "MIT",
+			"optional": true,
+			"os": [
+				"linux"
+			]
+		},
+		"node_modules/@rollup/rollup-linux-x64-musl": {
+			"version": "4.24.0",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"license": "MIT",
+			"optional": true,
+			"os": [
+				"linux"
+			]
+		},
+		"node_modules/@types/estree": {
+			"version": "1.0.6",
+			"dev": true,
+			"license": "MIT"
+		},
+		"node_modules/@types/node": {
+			"version": "18.15.13",
+			"license": "MIT"
+		},
+		"node_modules/aes-js": {
+			"version": "4.0.0-beta.5",
+			"license": "MIT"
+		},
+		"node_modules/command-exists": {
+			"version": "1.2.9",
+			"resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz",
+			"integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==",
+			"license": "MIT"
+		},
+		"node_modules/commander": {
+			"version": "8.3.0",
+			"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+			"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
+			"license": "MIT",
+			"engines": {
+				"node": ">= 12"
+			}
+		},
+		"node_modules/esbuild": {
+			"version": "0.21.5",
+			"dev": true,
+			"hasInstallScript": true,
+			"license": "MIT",
+			"bin": {
+				"esbuild": "bin/esbuild"
+			},
+			"engines": {
+				"node": ">=12"
+			},
+			"optionalDependencies": {
+				"@esbuild/aix-ppc64": "0.21.5",
+				"@esbuild/android-arm": "0.21.5",
+				"@esbuild/android-arm64": "0.21.5",
+				"@esbuild/android-x64": "0.21.5",
+				"@esbuild/darwin-arm64": "0.21.5",
+				"@esbuild/darwin-x64": "0.21.5",
+				"@esbuild/freebsd-arm64": "0.21.5",
+				"@esbuild/freebsd-x64": "0.21.5",
+				"@esbuild/linux-arm": "0.21.5",
+				"@esbuild/linux-arm64": "0.21.5",
+				"@esbuild/linux-ia32": "0.21.5",
+				"@esbuild/linux-loong64": "0.21.5",
+				"@esbuild/linux-mips64el": "0.21.5",
+				"@esbuild/linux-ppc64": "0.21.5",
+				"@esbuild/linux-riscv64": "0.21.5",
+				"@esbuild/linux-s390x": "0.21.5",
+				"@esbuild/linux-x64": "0.21.5",
+				"@esbuild/netbsd-x64": "0.21.5",
+				"@esbuild/openbsd-x64": "0.21.5",
+				"@esbuild/sunos-x64": "0.21.5",
+				"@esbuild/win32-arm64": "0.21.5",
+				"@esbuild/win32-ia32": "0.21.5",
+				"@esbuild/win32-x64": "0.21.5"
+			}
+		},
+		"node_modules/ethers": {
+			"version": "6.13.3",
+			"funding": [
+				{
+					"type": "individual",
+					"url": "https://github.com/sponsors/ethers-io/"
+				},
+				{
+					"type": "individual",
+					"url": "https://www.buymeacoffee.com/ricmoo"
+				}
+			],
+			"license": "MIT",
+			"dependencies": {
+				"@adraffy/ens-normalize": "1.10.1",
+				"@noble/curves": "1.2.0",
+				"@noble/hashes": "1.3.2",
+				"@types/node": "18.15.13",
+				"aes-js": "4.0.0-beta.5",
+				"tslib": "2.4.0",
+				"ws": "8.17.1"
+			},
+			"engines": {
+				"node": ">=14.0.0"
+			}
+		},
+		"node_modules/follow-redirects": {
+			"version": "1.15.9",
+			"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+			"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+			"funding": [
+				{
+					"type": "individual",
+					"url": "https://github.com/sponsors/RubenVerborgh"
+				}
+			],
+			"license": "MIT",
+			"engines": {
+				"node": ">=4.0"
+			},
+			"peerDependenciesMeta": {
+				"debug": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/js-sha3": {
+			"version": "0.8.0",
+			"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
+			"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==",
+			"license": "MIT"
+		},
+		"node_modules/memorystream": {
+			"version": "0.3.1",
+			"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+			"integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
+			"engines": {
+				"node": ">= 0.10.0"
+			}
+		},
+		"node_modules/nanoid": {
+			"version": "3.3.7",
+			"dev": true,
+			"funding": [
+				{
+					"type": "github",
+					"url": "https://github.com/sponsors/ai"
+				}
+			],
+			"license": "MIT",
+			"bin": {
+				"nanoid": "bin/nanoid.cjs"
+			},
+			"engines": {
+				"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+			}
+		},
+		"node_modules/os-tmpdir": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+			"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
+			"license": "MIT",
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/picocolors": {
+			"version": "1.1.0",
+			"dev": true,
+			"license": "ISC"
+		},
+		"node_modules/postcss": {
+			"version": "8.4.47",
+			"dev": true,
+			"funding": [
+				{
+					"type": "opencollective",
+					"url": "https://opencollective.com/postcss/"
+				},
+				{
+					"type": "tidelift",
+					"url": "https://tidelift.com/funding/github/npm/postcss"
+				},
+				{
+					"type": "github",
+					"url": "https://github.com/sponsors/ai"
+				}
+			],
+			"license": "MIT",
+			"dependencies": {
+				"nanoid": "^3.3.7",
+				"picocolors": "^1.1.0",
+				"source-map-js": "^1.2.1"
+			},
+			"engines": {
+				"node": "^10 || ^12 || >=14"
+			}
+		},
+		"node_modules/rollup": {
+			"version": "4.24.0",
+			"dev": true,
+			"license": "MIT",
+			"dependencies": {
+				"@types/estree": "1.0.6"
+			},
+			"bin": {
+				"rollup": "dist/bin/rollup"
+			},
+			"engines": {
+				"node": ">=18.0.0",
+				"npm": ">=8.0.0"
+			},
+			"optionalDependencies": {
+				"@rollup/rollup-android-arm-eabi": "4.24.0",
+				"@rollup/rollup-android-arm64": "4.24.0",
+				"@rollup/rollup-darwin-arm64": "4.24.0",
+				"@rollup/rollup-darwin-x64": "4.24.0",
+				"@rollup/rollup-linux-arm-gnueabihf": "4.24.0",
+				"@rollup/rollup-linux-arm-musleabihf": "4.24.0",
+				"@rollup/rollup-linux-arm64-gnu": "4.24.0",
+				"@rollup/rollup-linux-arm64-musl": "4.24.0",
+				"@rollup/rollup-linux-powerpc64le-gnu": "4.24.0",
+				"@rollup/rollup-linux-riscv64-gnu": "4.24.0",
+				"@rollup/rollup-linux-s390x-gnu": "4.24.0",
+				"@rollup/rollup-linux-x64-gnu": "4.24.0",
+				"@rollup/rollup-linux-x64-musl": "4.24.0",
+				"@rollup/rollup-win32-arm64-msvc": "4.24.0",
+				"@rollup/rollup-win32-ia32-msvc": "4.24.0",
+				"@rollup/rollup-win32-x64-msvc": "4.24.0",
+				"fsevents": "~2.3.2"
+			}
+		},
+		"node_modules/semver": {
+			"version": "5.7.2",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+			"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+			"license": "ISC",
+			"bin": {
+				"semver": "bin/semver"
+			}
+		},
+		"node_modules/solc": {
+			"version": "0.8.28",
+			"resolved": "https://registry.npmjs.org/solc/-/solc-0.8.28.tgz",
+			"integrity": "sha512-AFCiJ+b4RosyyNhnfdVH4ZR1+TxiL91iluPjw0EJslIu4LXGM9NYqi2z5y8TqochC4tcH9QsHfwWhOIC9jPDKA==",
+			"license": "MIT",
+			"dependencies": {
+				"command-exists": "^1.2.8",
+				"commander": "^8.1.0",
+				"follow-redirects": "^1.12.1",
+				"js-sha3": "0.8.0",
+				"memorystream": "^0.3.1",
+				"semver": "^5.5.0",
+				"tmp": "0.0.33"
+			},
+			"bin": {
+				"solcjs": "solc.js"
+			},
+			"engines": {
+				"node": ">=10.0.0"
+			}
+		},
+		"node_modules/source-map-js": {
+			"version": "1.2.1",
+			"dev": true,
+			"license": "BSD-3-Clause",
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/tmp": {
+			"version": "0.0.33",
+			"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+			"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+			"license": "MIT",
+			"dependencies": {
+				"os-tmpdir": "~1.0.2"
+			},
+			"engines": {
+				"node": ">=0.6.0"
+			}
+		},
+		"node_modules/tslib": {
+			"version": "2.4.0",
+			"license": "0BSD"
+		},
+		"node_modules/typescript": {
+			"version": "5.6.3",
+			"dev": true,
+			"license": "Apache-2.0",
+			"bin": {
+				"tsc": "bin/tsc",
+				"tsserver": "bin/tsserver"
+			},
+			"engines": {
+				"node": ">=14.17"
+			}
+		},
+		"node_modules/vite": {
+			"version": "5.4.8",
+			"dev": true,
+			"license": "MIT",
+			"dependencies": {
+				"esbuild": "^0.21.3",
+				"postcss": "^8.4.43",
+				"rollup": "^4.20.0"
+			},
+			"bin": {
+				"vite": "bin/vite.js"
+			},
+			"engines": {
+				"node": "^18.0.0 || >=20.0.0"
+			},
+			"funding": {
+				"url": "https://github.com/vitejs/vite?sponsor=1"
+			},
+			"optionalDependencies": {
+				"fsevents": "~2.3.3"
+			},
+			"peerDependencies": {
+				"@types/node": "^18.0.0 || >=20.0.0",
+				"less": "*",
+				"lightningcss": "^1.21.0",
+				"sass": "*",
+				"sass-embedded": "*",
+				"stylus": "*",
+				"sugarss": "*",
+				"terser": "^5.4.0"
+			},
+			"peerDependenciesMeta": {
+				"@types/node": {
+					"optional": true
+				},
+				"less": {
+					"optional": true
+				},
+				"lightningcss": {
+					"optional": true
+				},
+				"sass": {
+					"optional": true
+				},
+				"sass-embedded": {
+					"optional": true
+				},
+				"stylus": {
+					"optional": true
+				},
+				"sugarss": {
+					"optional": true
+				},
+				"terser": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/ws": {
+			"version": "8.17.1",
+			"license": "MIT",
+			"engines": {
+				"node": ">=10.0.0"
+			},
+			"peerDependencies": {
+				"bufferutil": "^4.0.1",
+				"utf-8-validate": ">=5.0.2"
+			},
+			"peerDependenciesMeta": {
+				"bufferutil": {
+					"optional": true
+				},
+				"utf-8-validate": {
+					"optional": true
+				}
+			}
+		}
+	}
 }
diff --git a/substrate/frame/revive/rpc/examples/js/package.json b/substrate/frame/revive/rpc/examples/js/package.json
index ec05cb74f7d1922b6b2e93befcfd3bf7c1ce42e1..3ae1f0fbd799a9e6be03292c0599e47b8e0f061a 100644
--- a/substrate/frame/revive/rpc/examples/js/package.json
+++ b/substrate/frame/revive/rpc/examples/js/package.json
@@ -6,11 +6,14 @@
   "scripts": {
     "dev": "vite",
     "build": "tsc && vite build",
-    "preview": "vite preview"
+    "preview": "vite preview",
+	"generate-types": "typechain --target=ethers-v6 'abi/*.json'"
   },
   "dependencies": {
-    "ethers": "^6.13.1",
-    "solc": "^0.8.28"
+    "@typechain/ethers-v6": "^0.5.1",
+    "ethers": "^6.13.4",
+    "solc": "^0.8.28",
+    "typechain": "^8.3.2"
   },
   "devDependencies": {
     "typescript": "^5.5.3",
diff --git a/substrate/frame/revive/rpc/examples/js/pvm-contracts.json b/substrate/frame/revive/rpc/examples/js/pvm-contracts.json
deleted file mode 100644
index be58e88a9a639dabef0ad5b8bd298624aa2aea4d..0000000000000000000000000000000000000000
--- a/substrate/frame/revive/rpc/examples/js/pvm-contracts.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
-  "event": {
-    "abi": [
-      {
-        "anonymous": false,
-        "inputs": [
-          {
-            "indexed": true,
-            "internalType": "address",
-            "name": "sender",
-            "type": "address"
-          },
-          {
-            "indexed": false,
-            "internalType": "uint256",
-            "name": "value",
-            "type": "uint256"
-          },
-          {
-            "indexed": false,
-            "internalType": "string",
-            "name": "message",
-            "type": "string"
-          }
-        ],
-        "name": "ExampleEvent",
-        "type": "event"
-      },
-      {
-        "inputs": [],
-        "name": "triggerEvent",
-        "outputs": [],
-        "stateMutability": "nonpayable",
-        "type": "function"
-      }
-    ],
-    "bytecode": "50564d00014214000000000000010700c13004c00040045f0600000000060000001300000018000000230000003500000063616c6c65726465706f7369745f6576656e74696e7075747365616c5f72657475726e7365745f696d6d757461626c655f6461746176616c75655f7472616e73666572726564051102912c0463616c6c9133066465706c6f790693b42602913cc8000c0111013001cb010a0327034303570374030c05270530054b055605d505e905f7050b062f06a7075d09e109460a9c0b400c730cdf0c710e800ef70ed20f2610bb10e710131133113b1152790e7a1004070f0a41040a0000012f8a3908890802871f1277e03b370000010a040713000a08000002297814160700000252780407100002088707130004071000020887071300130018875e08970a14a80b099c0128cc29bc1d29873107094a5279110b8b028801029c01109b52c91eacf405350709335279110b8b028801029c01109b52c91eacf4051e07091c027aff0288ff1108980b0bbb029cff089a09109b52c90f0cf113000211e003101c0315180316140215201211e0127601040704080610023dff16070800020d010004040710000352184e0211011726032c040326032804032603240403260320040326031c0403260318040326031404031607100403070607061004090610064b020211c003103c0315380316340215401211e05216040740040820061008d5fe070716020408080002260364000200000080260360000226035c000226035800022603540002260350000226034c000203681826034800020217e01277e003671c52710d171c0d17180d17140d17100d170c0d17080d17040d074e051101681c0182100183018914018a1c018b0c018c040187180188080cba0a0cc9090ca9090c87070c23080c87070c97070f077e0104074004082006100a3afe07077b01016718017450017040017b58017c48017a5401724c0173440e2808128800ff000e29180c9808122900ff000999080922180c92090c980803681c0e3808128800ff000e39180c9808123900ff000999080933180c93090c89030ea808128800ff000ea9180c980812a900ff0009990809aa180ca9090c89020ec808128800ff000ec9180c980812c900ff0009990809cc180cc9090c890c0eb808128800ff000eb9180c980812b900ff0009990809bb180cb9090c98080e0908129900ff000e0b180cb909120b00ff0009bb080900180cb00b0cb9090e4b0812bb00ff000e4a180cba0a124b00ff0009bb080944180cb40b0cba0a0ca9090cc8080c98080c3209016a1c0ca9090c98080f086e01681801885c0e8908129900ff000e8a180ca909128700ff000977080988180c87070c970703671c040806100cfbfc07073c0a080c000207080b04073004034e041101671c040806100edefc07071f01681801671c087808040704094e031104070408061010c2fc0f070400040808000204070104090400124e03110211a003105c0315580316540215601211e004074004082006101491fc0f07040004061004030a0710040303171c0a041404030a031804030a092c04030a082804030a002004030a0c2404032797278a54970a27cb270754cb070c980b54ba070316180a0b1c04032742011a1c1baa041faa0154420a27b2273654b2060cb30b54b60a0cc9090c80080c980854870a0409080002260364000200000080260360000226035c000226035800022603540002260350000226034c00022603480002070a0b010a071000030f47ede48fb7020103191c0d113c0d11380d11340d11300d112c0d11280d11240d11200217204e0511011230011820011934011a3c011b2c011c240116380117280cba0a0cc9090ca9090c67070c28080c87070c97070f07b10001171801721c017318017414017a100178017c0c017604017708028bfc248b0808860b02bbff1c6b09246b0b53980b0278ff08b8092479002489081b7601146c060868081cc80624c8085360081c97070c6707537b0802a7ff0878082478071ba8011484080878092489085377080c4a071b77011473090898082498082473071472070887072d074604070408061016f9fa07076bfe040808000204070104094e0304001805ca00061018c7000407040806101ad5fa070747fe040808000204070104094e0304001c05c80006101cc50004074004082006101eaffa070721fe011b1c01b24c01b34401ba5401b94801bc4001b65001b8580c6c0c0c98080cc8080c3a090c29090c98080e8908129900ff000e8a180ca909098a18128800ff000988080ca8080c98080f08d4fd01b85c0e8908129900ff000e8a180ca909128700ff000977080988180c87070c9707031718040852b606102030fa0707a2fd011818086808040704090400224e03110211fc0310040704080610240efa0f070400040808000204070104090400264e0311021140ff0310bc000315b8000316b4000215c0001211e05216040740040820061028d6f90707e70a04040800020a036400020a084800020a0a6000020a025000020a0c4c00020e8b0812b900ff000e8b180cb909128b00ff0009bb080988180cb8080c98080368780ec808128800ff000ec9180c980812c900ff0009990809cc180cc9090c89000ea808128800ff000ea9180c980812a900ff0009990809aa180ca9090c890a0e3808128800ff000e39180c9808123900ff000999080933180c93090c890902a801036a6c1baaff0369741b99c0548a090e2808128800ff000e2a180ca808122a00ff0009aa080a0b5400020922180ca20a0c8a020eb808128800ff000eba180ca80812ba00ff0009aa080a0c58000209bb180cba0a0c8a030ec808128800ff000eca180ca80812ca00ff0009aa0803647c0a0b5c000209cc180cca0a0c8a0c0eb808128800ff000eba180ca80812b700ff0009770809bb180cb7070c870a0362680167780c72070360700363640c03080c8707036c60036a5c0cca08036854568903675856790709190904074004082006102a5ef807076f0901677402784003685024780701686c08780903694824890b53770b01675c08b70024700701686008780224820c53770c53bb0c016764087c0c247c0b01676808b70424740853bb0801677008870a247a080163780883030e3708127700ff000e38180c7808123700ff000977080933180c73070c870703674c0ea708127700ff000ea9180c970712a900ff0009990809aa180ca9090c97070367440e4708127700ff000e49180c9707124900ff000999080944180c94090c79040ec708127700ff000ec9180c970712c900ff0009990809cc180cc9090c79030e2708127700ff000e29180c9707122900ff000999080922180c92090c79020e0908129900ff000e0a180ca909120a00ff0009aa080900180ca00a0ca9090167480e7a0812aa00ff000e78180ca808127a00ff0009aa08097c180cca0a0ca8080167500e7a0812aa00ff000e7c180cca0a127b00ff0009bb08097c180ccb0b0cba0a016b7c03ba5c03b85803b95403b25003b34c03b44801674403b74401676c0168680c87070168600169780c98080c870701685c0169700c98080169640c98080c870701684c03b8400f07c80704082001677406102ca8f60707b9070162741b27e01f770101696c279854980701685c2788016a6027a953a8090168545387090167642777016a6827a853a708016c7027c7016b7827ba53b70a0cbc0753780a01675853790a01677c0827080d181c0000000b0d18180d18140d18100d180c0d18080d18040368440d080f0a470702272004082003676006102e24f60707350701687c0167600878080d181c0d18180d18140d18100d180c0d1808726c640d18046f20776f0368340d0848656c6c026780004e0167900003671401678c000367180167880003671c0167840003672001678000036724040740040820061030bff50707d00601677c017250017340017458017048017c54017b4c0179440eb808128800ff000eba180ca80812ba00ff0009aa0809bb180cba0a0ca8080368700e9808128800ff000e9a180ca808129a00ff0009aa080999180ca9090c98080368680ec808128800ff000ec9180c980812c900ff0009990809cc180cc9090c890b0e0808128800ff000e09180c9808120900ff000999080900180c90090c89000e4808128800ff000e49180c9808124900ff000999080944180c94090c890c0e3808128800ff000e39180c9808123900ff000999080933180c93090c890a0e2808128800ff000e29180c9808122900ff000999080922180c92090c9808036a5c0368540ca808036058036c6c0c0c090c9808036b640169680cb909016a700ca9090c98080f08ae0501687c01885c0e8908129900ff000e8a180ca909128700ff000977080988180c87070c970704082003677806103269f407077a05016a7c016778087a0a527b0d1a1c000030390d1a180d1a140d1a100d1a0c0d1a080d1a0401686c27891bb7e01f7c0103694854890c01676427780160542704530804016770277801635827325338020169682798016b5c27b753b8070cb9085382070168700c98080cb3090c98080169640c090903694c03644054940c03685003673c54870c036a100d0a0168780f0ce804028720040820036738061034c5f30707d60401677c0168380887070d171c000000400d17180d17140d17100d170c0d17080d17040d0704082001677406103692f30707a3040169781b97c01f770101686c016a48548a0701684c016a40548a07016850016a3c548a070f077b0401674401781c03684801781803687401781403684001781003683c01780c03683801780803683001780403682c017703674402974004082003672806103826f3070737040167781b77a001686c568701684c5687016850568701687c016928089808016c2c038c04016a44038a016b30038b0801643803840c01623c03821001604003801401697403891801694803891c0707e6030ea808128800ff000ea9180c980812a900ff0009990809aa180ca9090c98080368500ec808128800ff000ec9180c980812c900ff0009990809ca180ca9090c890c0eb808128800ff000eb9180c980812b900ff0009990809ba180ca9090c89030e4808128800ff000e49180c9808124900ff00099908094a180ca9090c89040e2808128800ff000e29180c9808122900ff00099908092a180ca9090c89020e0808128800ff000e09180c9808120900ff00099908090a180ca9090c8900016a740ea808128800ff000ea9180c980812a900ff0009990809aa180ca9090c980803684403633c0c38080362300169500c92090c9808036c4003602c0cc0090364380c49090c98080f08dc02016a480ea808128800ff000ea9180c980812a700ff0009770809a9180c97070c780801677802776003674c03687406103a94f10707a50201676001687406103c85f10707960201677801684c247807528b01686c08780903690c24890853770801676408870903692824790701695408790a036a48249a0953770953880901677008790903696024790701685808780903696424890853770801676808780803686c24780703676801677c08b70701683401697406103e58f101684c016974089808016a4401670c08a7070368702498080887021ca20924a20a53980a01682c016928088909016730016c48087c0c24890b08cb0b08a904249409089b031c730c24730b24840753c70b1c84070cc707537a0b01683801676008870724870a01683c016c64088c0c08ac0c1c8c09248c08539a08087b0b247b07087c0024c00953770901675c016a5008a707016a6808a707016a40016c6c08ac0c24ac0a08a70708c80824c80a08a7070889092489080887070cb4080c98080c73070c02090c98080c87070f07530104082001677006104033f00707440101687c0167700878080d181c0d18180d18140d18100d180c0d18080d180401697402971f249709016a4408a909129901127be01bbaa01faa0154990a0d080167780f0aff0002b86003687c061042dfef0707f0000217c01277e052710d171c8c16c7d00d1718622fa9a50d1714af827c120d17104a032b310d170cec4214070d1708f0370dae0d170487296ff20d071585375401681403783c01681803783801681c03783401682003783001682403782c0d17280d17240d1720040802016910016a7c4e01025140ff0110bc000115b8000116b4000211c000130004082004070610444aef07075b01687c0d181c0d18180d18140d18100d180c0d18080d18040d084e487b710407040408200610461eef07072f01687c0d1820000000410d181c0d18180d18140d18100d180c0d18080d18040408240407061048f2ee0f07040004080800020407010409244e03040704004a0581ef040706104a7cef04070106104c74ef00a58424092a241452482549495a52292da994644a2a2549920a21422d8410420821119224290911028410420809494a92243529499224491249882449928424244912929024094948928424244942129224210949929084244992244912929024292424348524a956c890d2244992902124841042a854928492a492244908104208218408014992244993244992244924494a9224499224499224499224499224a9102195840a115249484224499224499290242489242421495221924a53850c298d8888948408218410129290244948429224242149129290244992242421214942121292242421094912929024499224494a91844892244992244992244992242421499290842449421292242109499290842449484292242109499284242449922449922449922449242192a4a49424a5a4942449024992a448122249922408248891482412494224499224242149929084244942129224210949929084244948429224242149922449922491242421499210490a2449929224a5a494949224499224494a2409912490244949882449922489244992244952928448524a4992942449922491908424494212922421094992908424494842922424214992908424499224499244129290244912220991a424499224499224499224499284244992244992244992244992244992244992244992244992248924449224499224499294484224050281402010089224499224498a8888524892244990842490244952c8905452480800"
-  },
-  "revert": {
-    "abi": [
-      {
-        "inputs": [],
-        "stateMutability": "nonpayable",
-        "type": "constructor"
-      },
-      {
-        "inputs": [],
-        "name": "doRevert",
-        "outputs": [],
-        "stateMutability": "nonpayable",
-        "type": "function"
-      }
-    ],
-    "bytecode": "50564d0001ba09000000000000010700c13004c0004004440400000000050000001000000022000000696e7075747365616c5f72657475726e7365745f696d6d757461626c655f6461746176616c75655f7472616e7366657272656405110288020463616c6c8809066465706c6f79068947170288126700aa00af00ce006901a802c502e102f5021303ab04c604cf04eb043d06d50632078f07c907dc07ea070908110852790e7a1004070f0a41040a0000012f8a3908890802871f1277e03b370000010a040713000a0800000229781416070000025278040710000208870713000407100002088707130013000211e003101c0315180316140215201211e0127601040704080610029d16070400020d010004040710000352184e11011726032c040326032804032603240403260320040326031c0403260318040326031404031607100403070607061004090610064b020211c003103c0315380316340215401211e0521604074004082006100837ff07071602040804000226036000020000008026035c000226035800022603540002260350000226034c0002260348000203681826034400020217e01277e003671c52710d171c0d17180d17140d17100d170c0d17080d17040d074e031101681c0182100183018914018a1c018b0c018c040187180188080cba0a0cc9090ca9090c87070c23080c87070c97070f077e0104074004082006100a9cfe07077b01016718017450017040017b58017c48017a5401724c0173440e2808128800ff000e29180c9808122900ff000999080922180c92090c980803681c0e3808128800ff000e39180c9808123900ff000999080933180c93090c89030ea808128800ff000ea9180c980812a900ff0009990809aa180ca9090c89020ec808128800ff000ec9180c980812c900ff0009990809cc180cc9090c890c0eb808128800ff000eb9180c980812b900ff0009990809bb180cb9090c98080e0908129900ff000e0b180cb909120b00ff0009bb080900180cb00b0cb9090e4b0812bb00ff000e4a180cba0a124b00ff0009bb080944180cb40b0cba0a0ca9090cc8080c98080c3209016a1c0ca9090c98080f086e01681801885c0e8908129900ff000e8a180ca909128700ff000977080988180c87070c970703671c040806100c5dfd07073c0a0808000207080b04073004034e021101671c040806100e40fd07071f01681801671c087808040704094e01110407040806101024fd0f070400040804000204070104090400124e011102118003107c031578031674021580001211e0040740040820061014f2fc0f07040004061004030a0710040303173c0a041404030a031804030a092c04030a082804030a002004030a0c2404032797278a54970a27cb270754cb070c980b54ba070316380a0b1c04032742011a3c1baa041faa0154420a27b2273654b2060cb30b54b60a0cc9090c80080c980854870a040904000226036000020000008026035c000226035800022603540002260350000226034c000226034800022603440002070a0b010a071000030f47afc874d2020103193c0d115c0d11580d11540d11500d114c0d11480d11440d11400217404e0311011250011840011954011a5c011b4c011c440116580117480cba0a0cc9090ca9090c67070c28080c87070c97070f07b10001173801721c017318017414017a100178017c0c017604017708028bfc248b0808860b02bbff1c6b09246b0b53980b0278ff08b8092479002489081b7601146c060868081cc80624c8085360081c97070c6707537b0802a7ff0878082478071ba8011484080878092489085377080c4a071b77011473090898082498082473071472070887072d0741040704080610165afb07076bfe040804000204070104094e01040018051e030610181b030407040806101a36fb070747fe040804000204070104094e011104074004082006101c1afb07072bfe01103c010250010340010458010b48010c54010a4c0108440ea608126600ff000ea9180c690912a600ff0009660809aa180c6a0a0ca9090319380e8908129900ff000e8a180ca909128a00ff0009aa080988180ca8080c98080318340ec808128800ff000ec9180c980812c900ff0009990809cc180cc9090c890c0eb808128800ff000eb9180c980812b900ff0009990809bb180cb9090c890a0e4808128800ff000e49180c9808124900ff000999080944180c94090c89040e3808128800ff000e39180c9808123900ff000999080933180c93090c89030e2808128800ff000e29180c9808122900ff000999080922180c92060c860b0c3b080ca4090c98080119340cc9090116380c69090c98080f0818fd52b6031320031a24031c2803142c01085c0e8908129900ff000e8a180ca909128700ff000977080988180c87070c970704082003173006101ec8f90707d9fc011230011a3c082a0a0d0a08c379a00113382737011424274b53470b011c3427c701182027895387090c8c07537b09011b2827b727605367000cb6060cc3070d1a1c0d1a180d1a140d1a100d1a0c0d1a080c8408011b2c27bc0c78081b27fc1f770154bc070316385460075489070d1a040f0764fc031c20031824031028031934031a1c011730027704040820527606102030f9070741fc01173c0867070d171c000000200d17180d17140d17100d170c0d17080d17040118301b88dc1f880101192c011a20549a08011928011a3854a908011934011a2454a9080d070f08f8fb0117300276240408205267061022d3f80707e4fb01173c0867070d171c0000000e0d17180d17140d17100d170c0d17080d17040118301b88bc1f880101192c011a20549a08011928011a3854a908011934011a2454a9080d070f089bfb011730027644040820526706102476f8070787fb01173c0867070d171c0d17180d17140d17100d170c67650d1708657373610d17047274206d0d07726576650408640117300610263cf807074dfb04070104096401181c0400284e01110211fc03100407040806102a1bf80f070400040804000204070104094e01040704002c054bf8040706102c46f804070106102e3ef800a58424092a241452482549928a10a10b21841042488424494a4284002184104242929224494d4a9224499244122249922421094992842424494212922421094992908424494842922424214992244992842424490a09094d2149aa1532a434492249c81012420821542a494249524992240408218410428480244992a449922449922492242549922449922449922449922449925488904a428508a9498824499284242449129290244948429224242149129290240949489284242449922449942449484292242192042925a524a924499224254992449224492192409224499224495224294412489224499224498a24854892240402411222499a2a64489514120200"
-  }
-}
\ No newline at end of file
diff --git a/substrate/frame/revive/rpc/examples/js/pvm/event.polkavm b/substrate/frame/revive/rpc/examples/js/pvm/event.polkavm
new file mode 100644
index 0000000000000000000000000000000000000000..859c1cdf5d3e97c7df8cbad6a0dc0cbd5f8d6388
Binary files /dev/null and b/substrate/frame/revive/rpc/examples/js/pvm/event.polkavm differ
diff --git a/substrate/frame/revive/rpc/examples/js/pvm/piggyBank.polkavm b/substrate/frame/revive/rpc/examples/js/pvm/piggyBank.polkavm
new file mode 100644
index 0000000000000000000000000000000000000000..1a45c15d53f68431b7e5c1dff297c768e1160e97
Binary files /dev/null and b/substrate/frame/revive/rpc/examples/js/pvm/piggyBank.polkavm differ
diff --git a/substrate/frame/revive/rpc/examples/js/pvm/revert.polkavm b/substrate/frame/revive/rpc/examples/js/pvm/revert.polkavm
new file mode 100644
index 0000000000000000000000000000000000000000..7505c402f21b7f8a16914f1f067f94eebb9b3c96
Binary files /dev/null and b/substrate/frame/revive/rpc/examples/js/pvm/revert.polkavm differ
diff --git a/substrate/frame/revive/rpc/examples/js/src/build-contracts.ts b/substrate/frame/revive/rpc/examples/js/src/build-contracts.ts
index 3e9d036d1b7d5d16292a7af9b0406093350b7f5c..c6b7700d1ccf44a4e7f38e609abab71749559cbb 100644
--- a/substrate/frame/revive/rpc/examples/js/src/build-contracts.ts
+++ b/substrate/frame/revive/rpc/examples/js/src/build-contracts.ts
@@ -25,11 +25,10 @@ function evmCompile(sources: CompileInput) {
 
 console.log('Compiling contracts...')
 
-let pvmContracts: Map<string, { abi: Abi; bytecode: string }> = new Map()
-let evmContracts: Map<string, { abi: Abi; bytecode: string }> = new Map()
 const input = [
 	{ file: 'Event.sol', contract: 'EventExample', keypath: 'event' },
 	{ file: 'Revert.sol', contract: 'RevertExample', keypath: 'revert' },
+	{ file: 'PiggyBank.sol', contract: 'PiggyBank', keypath: 'piggyBank' },
 ]
 
 for (const { keypath, contract, file } of input) {
@@ -41,16 +40,17 @@ for (const { keypath, contract, file } of input) {
 		console.log(`Compile with solc ${file}`)
 		const out = JSON.parse(evmCompile(input))
 		const entry = out.contracts[file][contract]
-		evmContracts.set(keypath, { abi: entry.abi, bytecode: entry.evm.bytecode.object })
+		writeFileSync(join('evm', `${keypath}.bin`), Buffer.from(entry.evm.bytecode.object, 'hex'))
+		writeFileSync(join('abi', `${keypath}.json`), JSON.stringify(entry.abi, null, 2))
 	}
 
 	{
 		console.log(`Compile with revive ${file}`)
 		const out = await compile(input)
 		const entry = out.contracts[file][contract]
-		pvmContracts.set(keypath, { abi: entry.abi, bytecode: entry.evm.bytecode.object })
+		writeFileSync(
+			join('pvm', `${keypath}.polkavm`),
+			Buffer.from(entry.evm.bytecode.object, 'hex')
+		)
 	}
 }
-
-writeFileSync('pvm-contracts.json', JSON.stringify(Object.fromEntries(pvmContracts), null, 2))
-writeFileSync('evm-contracts.json', JSON.stringify(Object.fromEntries(evmContracts), null, 2))
diff --git a/substrate/frame/revive/rpc/examples/js/src/event.ts b/substrate/frame/revive/rpc/examples/js/src/event.ts
index 95e630a434616e68fb78875033641c2caeb5b3d5..94cc2560272e6813a17880d6fec2eee3027c9f25 100644
--- a/substrate/frame/revive/rpc/examples/js/src/event.ts
+++ b/substrate/frame/revive/rpc/examples/js/src/event.ts
@@ -3,8 +3,8 @@ import { call, getContract, deploy } from './lib.ts'
 
 try {
 	const { abi, bytecode } = getContract('event')
-	const address = await deploy(bytecode, abi)
-	const receipt = await call('triggerEvent', address, abi)
+	const contract = await deploy(bytecode, abi)
+	const receipt = await call('triggerEvent', await contract.getAddress(), abi)
 	if (receipt) {
 		for (const log of receipt.logs) {
 			console.log('Event log:', JSON.stringify(log, null, 2))
diff --git a/substrate/frame/revive/rpc/examples/js/src/lib.ts b/substrate/frame/revive/rpc/examples/js/src/lib.ts
index 40f2d6f058244da1bbb61d6263b74911730acb67..975d8faf15b31327783fb4aecc63f57895dc92fb 100644
--- a/substrate/frame/revive/rpc/examples/js/src/lib.ts
+++ b/substrate/frame/revive/rpc/examples/js/src/lib.ts
@@ -10,6 +10,7 @@ import { readFileSync } from 'node:fs'
 import type { compile } from '@parity/revive'
 import { spawn } from 'node:child_process'
 import { parseArgs } from 'node:util'
+import { BaseContract } from 'ethers'
 
 type CompileOutput = Awaited<ReturnType<typeof compile>>
 type Abi = CompileOutput['contracts'][string][string]['abi']
@@ -41,7 +42,7 @@ if (geth) {
 			'--http.api',
 			'web3,eth,debug,personal,net',
 			'--http.port',
-			'8545',
+			'8546',
 			'--dev',
 			'--verbosity',
 			'0',
@@ -55,10 +56,14 @@ if (geth) {
 }
 
 export const provider = new JsonRpcProvider(
-	westend ? 'https://westend-asset-hub-eth-rpc.polkadot.io' : 'http://localhost:8545'
+	westend
+		? 'https://westend-asset-hub-eth-rpc.polkadot.io'
+		: geth
+			? 'http://localhost:8546'
+			: 'http://localhost:8545'
 )
 
-const signer = privateKey ? new Wallet(privateKey, provider) : await provider.getSigner()
+export const signer = privateKey ? new Wallet(privateKey, provider) : await provider.getSigner()
 console.log(`Signer address: ${await signer.getAddress()}, Nonce: ${await signer.getNonce()}`)
 
 /**
@@ -66,18 +71,16 @@ console.log(`Signer address: ${await signer.getAddress()}, Nonce: ${await signer
  * @param name - the contract name
  */
 export function getContract(name: string): { abi: Abi; bytecode: string } {
-	const file = geth
-		? readFileSync('evm-contracts.json', 'utf8')
-		: readFileSync('pvm-contracts.json', 'utf8')
-	const contracts = JSON.parse(file) as Record<string, { abi: Abi; bytecode: string }>
-	return contracts[name]
+	const bytecode = geth ? readFileSync(`evm/${name}.bin`) : readFileSync(`pvm/${name}.polkavm`)
+	const abi = JSON.parse(readFileSync(`abi/${name}.json`, 'utf8')) as Abi
+	return { abi, bytecode: Buffer.from(bytecode).toString('hex') }
 }
 
 /**
  * Deploy a contract
  * @returns the contract address
  **/
-export async function deploy(bytecode: string, abi: Abi, args: any[] = []): Promise<string> {
+export async function deploy(bytecode: string, abi: Abi, args: any[] = []): Promise<BaseContract> {
 	console.log('Deploying contract with', args)
 	const contractFactory = new ContractFactory(abi, bytecode, signer)
 
@@ -85,7 +88,8 @@ export async function deploy(bytecode: string, abi: Abi, args: any[] = []): Prom
 	await contract.waitForDeployment()
 	const address = await contract.getAddress()
 	console.log(`Contract deployed: ${address}`)
-	return address
+
+	return contract
 }
 
 /**
diff --git a/substrate/frame/revive/rpc/examples/js/src/piggy-bank.ts b/substrate/frame/revive/rpc/examples/js/src/piggy-bank.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7a8edbde36626f097b7e87ef0ec0e5d5812d20f8
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/src/piggy-bank.ts
@@ -0,0 +1,24 @@
+import { provider, call, getContract, deploy } from './lib.ts'
+import { parseEther } from 'ethers'
+import { PiggyBank } from '../types/ethers-contracts/PiggyBank'
+
+try {
+	const { abi, bytecode } = getContract('piggyBank')
+	const contract = (await deploy(bytecode, abi)) as PiggyBank
+	const address = await contract.getAddress()
+
+	let receipt = await call('deposit', address, abi, [], {
+		value: parseEther('10.0'),
+	})
+	console.log('Deposit receipt:', receipt?.status)
+	console.log(`Contract balance: ${await provider.getBalance(address)}`)
+
+	console.log('deposit: ', await contract.getDeposit())
+
+	receipt = await call('withdraw', address, abi, [parseEther('5.0')])
+	console.log('Withdraw receipt:', receipt?.status)
+	console.log(`Contract balance: ${await provider.getBalance(address)}`)
+	console.log('deposit: ', await contract.getDeposit())
+} catch (err) {
+	console.error(err)
+}
diff --git a/substrate/frame/revive/rpc/examples/js/src/revert.ts b/substrate/frame/revive/rpc/examples/js/src/revert.ts
index 5fb3ccde6fae3a68029a4fabb78332762042f011..ea1bf4eceeb9c3991412b0d9de9c9c0513b45815 100644
--- a/substrate/frame/revive/rpc/examples/js/src/revert.ts
+++ b/substrate/frame/revive/rpc/examples/js/src/revert.ts
@@ -3,8 +3,8 @@ import { call, getContract, deploy } from './lib.ts'
 
 try {
 	const { abi, bytecode } = getContract('revert')
-	const address = await deploy(bytecode, abi)
-	await call('doRevert', address, abi)
+	const contract = await deploy(bytecode, abi)
+	await call('doRevert', await contract.getAddress(), abi)
 } catch (err) {
 	console.error(err)
 }
diff --git a/substrate/frame/revive/rpc/examples/js/src/transfer.ts b/substrate/frame/revive/rpc/examples/js/src/transfer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ae2dd50f2af868b84b5b29ad70b6da5df78ebb60
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/src/transfer.ts
@@ -0,0 +1,17 @@
+import { parseEther } from 'ethers'
+import { provider, signer } from './lib.ts'
+
+const recipient = '0x75E480dB528101a381Ce68544611C169Ad7EB342'
+try {
+	console.log(`Signer balance:    ${await provider.getBalance(signer.address)}`)
+	console.log(`Recipient balance: ${await provider.getBalance(recipient)}`)
+	await signer.sendTransaction({
+		to: recipient,
+		value: parseEther('1.0'),
+	})
+	console.log(`Sent:              ${parseEther('1.0')}`)
+	console.log(`Signer balance:    ${await provider.getBalance(signer.address)}`)
+	console.log(`Recipient balance: ${await provider.getBalance(recipient)}`)
+} catch (err) {
+	console.error(err)
+}
diff --git a/substrate/frame/revive/rpc/examples/js/tsconfig.json b/substrate/frame/revive/rpc/examples/js/tsconfig.json
index 0511b9f0e041a443efb98b2e1c3741a02b443b86..55cb8379e886a60de1b8b27109d29f4e396708c2 100644
--- a/substrate/frame/revive/rpc/examples/js/tsconfig.json
+++ b/substrate/frame/revive/rpc/examples/js/tsconfig.json
@@ -1,23 +1,23 @@
 {
-  "compilerOptions": {
-    "target": "ES2020",
-    "useDefineForClassFields": true,
-    "module": "ESNext",
-    "lib": ["ES2020", "DOM", "DOM.Iterable"],
-    "skipLibCheck": true,
+	"compilerOptions": {
+		"target": "ES2020",
+		"useDefineForClassFields": true,
+		"module": "ESNext",
+		"lib": ["ES2020", "DOM", "DOM.Iterable"],
+		"skipLibCheck": true,
 
-    /* Bundler mode */
-    "moduleResolution": "bundler",
-    "allowImportingTsExtensions": true,
-    "isolatedModules": true,
-    "moduleDetection": "force",
-    "noEmit": true,
+		/* Bundler mode */
+		"moduleResolution": "bundler",
+		"allowImportingTsExtensions": true,
+		"isolatedModules": true,
+		"moduleDetection": "force",
+		"noEmit": true,
 
-    /* Linting */
-    "strict": true,
-    "noUnusedLocals": true,
-    "noUnusedParameters": true,
-    "noFallthroughCasesInSwitch": true
-  },
-  "include": ["src"]
+		/* Linting */
+		"strict": true,
+		"noUnusedLocals": true,
+		"noUnusedParameters": true,
+		"noFallthroughCasesInSwitch": true
+	},
+	"include": ["src"]
 }
diff --git a/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/Event.ts b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/Event.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d65f953969f0c3158fb527103021f59dd960598c
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/Event.ts
@@ -0,0 +1,117 @@
+/* Autogenerated file. Do not edit manually. */
+/* tslint:disable */
+/* eslint-disable */
+import type {
+	BaseContract,
+	BigNumberish,
+	BytesLike,
+	FunctionFragment,
+	Result,
+	Interface,
+	EventFragment,
+	AddressLike,
+	ContractRunner,
+	ContractMethod,
+	Listener,
+} from 'ethers'
+import type {
+	TypedContractEvent,
+	TypedDeferredTopicFilter,
+	TypedEventLog,
+	TypedLogDescription,
+	TypedListener,
+	TypedContractMethod,
+} from './common'
+
+export interface EventInterface extends Interface {
+	getFunction(nameOrSignature: 'triggerEvent'): FunctionFragment
+
+	getEvent(nameOrSignatureOrTopic: 'ExampleEvent'): EventFragment
+
+	encodeFunctionData(functionFragment: 'triggerEvent', values?: undefined): string
+
+	decodeFunctionResult(functionFragment: 'triggerEvent', data: BytesLike): Result
+}
+
+export namespace ExampleEventEvent {
+	export type InputTuple = [sender: AddressLike, value: BigNumberish, message: string]
+	export type OutputTuple = [sender: string, value: bigint, message: string]
+	export interface OutputObject {
+		sender: string
+		value: bigint
+		message: string
+	}
+	export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>
+	export type Filter = TypedDeferredTopicFilter<Event>
+	export type Log = TypedEventLog<Event>
+	export type LogDescription = TypedLogDescription<Event>
+}
+
+export interface Event extends BaseContract {
+	connect(runner?: ContractRunner | null): Event
+	waitForDeployment(): Promise<this>
+
+	interface: EventInterface
+
+	queryFilter<TCEvent extends TypedContractEvent>(
+		event: TCEvent,
+		fromBlockOrBlockhash?: string | number | undefined,
+		toBlock?: string | number | undefined
+	): Promise<Array<TypedEventLog<TCEvent>>>
+	queryFilter<TCEvent extends TypedContractEvent>(
+		filter: TypedDeferredTopicFilter<TCEvent>,
+		fromBlockOrBlockhash?: string | number | undefined,
+		toBlock?: string | number | undefined
+	): Promise<Array<TypedEventLog<TCEvent>>>
+
+	on<TCEvent extends TypedContractEvent>(
+		event: TCEvent,
+		listener: TypedListener<TCEvent>
+	): Promise<this>
+	on<TCEvent extends TypedContractEvent>(
+		filter: TypedDeferredTopicFilter<TCEvent>,
+		listener: TypedListener<TCEvent>
+	): Promise<this>
+
+	once<TCEvent extends TypedContractEvent>(
+		event: TCEvent,
+		listener: TypedListener<TCEvent>
+	): Promise<this>
+	once<TCEvent extends TypedContractEvent>(
+		filter: TypedDeferredTopicFilter<TCEvent>,
+		listener: TypedListener<TCEvent>
+	): Promise<this>
+
+	listeners<TCEvent extends TypedContractEvent>(
+		event: TCEvent
+	): Promise<Array<TypedListener<TCEvent>>>
+	listeners(eventName?: string): Promise<Array<Listener>>
+	removeAllListeners<TCEvent extends TypedContractEvent>(event?: TCEvent): Promise<this>
+
+	triggerEvent: TypedContractMethod<[], [void], 'nonpayable'>
+
+	getFunction<T extends ContractMethod = ContractMethod>(key: string | FunctionFragment): T
+
+	getFunction(nameOrSignature: 'triggerEvent'): TypedContractMethod<[], [void], 'nonpayable'>
+
+	getEvent(
+		key: 'ExampleEvent'
+	): TypedContractEvent<
+		ExampleEventEvent.InputTuple,
+		ExampleEventEvent.OutputTuple,
+		ExampleEventEvent.OutputObject
+	>
+
+	filters: {
+		'ExampleEvent(address,uint256,string)': TypedContractEvent<
+			ExampleEventEvent.InputTuple,
+			ExampleEventEvent.OutputTuple,
+			ExampleEventEvent.OutputObject
+		>
+		ExampleEvent: TypedContractEvent<
+			ExampleEventEvent.InputTuple,
+			ExampleEventEvent.OutputTuple,
+			ExampleEventEvent.OutputObject
+		>
+	}
+}
diff --git a/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/PiggyBank.ts b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/PiggyBank.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ca137fcc8b30aec6ebf9fda80248f890ed5668d7
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/PiggyBank.ts
@@ -0,0 +1,96 @@
+/* Autogenerated file. Do not edit manually. */
+/* tslint:disable */
+/* eslint-disable */
+import type {
+	BaseContract,
+	BigNumberish,
+	BytesLike,
+	FunctionFragment,
+	Result,
+	Interface,
+	ContractRunner,
+	ContractMethod,
+	Listener,
+} from 'ethers'
+import type {
+	TypedContractEvent,
+	TypedDeferredTopicFilter,
+	TypedEventLog,
+	TypedListener,
+	TypedContractMethod,
+} from './common'
+
+export interface PiggyBankInterface extends Interface {
+	getFunction(nameOrSignature: 'deposit' | 'getDeposit' | 'owner' | 'withdraw'): FunctionFragment
+
+	encodeFunctionData(functionFragment: 'deposit', values?: undefined): string
+	encodeFunctionData(functionFragment: 'getDeposit', values?: undefined): string
+	encodeFunctionData(functionFragment: 'owner', values?: undefined): string
+	encodeFunctionData(functionFragment: 'withdraw', values: [BigNumberish]): string
+
+	decodeFunctionResult(functionFragment: 'deposit', data: BytesLike): Result
+	decodeFunctionResult(functionFragment: 'getDeposit', data: BytesLike): Result
+	decodeFunctionResult(functionFragment: 'owner', data: BytesLike): Result
+	decodeFunctionResult(functionFragment: 'withdraw', data: BytesLike): Result
+}
+
+export interface PiggyBank extends BaseContract {
+	connect(runner?: ContractRunner | null): PiggyBank
+	waitForDeployment(): Promise<this>
+
+	interface: PiggyBankInterface
+
+	queryFilter<TCEvent extends TypedContractEvent>(
+		event: TCEvent,
+		fromBlockOrBlockhash?: string | number | undefined,
+		toBlock?: string | number | undefined
+	): Promise<Array<TypedEventLog<TCEvent>>>
+	queryFilter<TCEvent extends TypedContractEvent>(
+		filter: TypedDeferredTopicFilter<TCEvent>,
+		fromBlockOrBlockhash?: string | number | undefined,
+		toBlock?: string | number | undefined
+	): Promise<Array<TypedEventLog<TCEvent>>>
+
+	on<TCEvent extends TypedContractEvent>(
+		event: TCEvent,
+		listener: TypedListener<TCEvent>
+	): Promise<this>
+	on<TCEvent extends TypedContractEvent>(
+		filter: TypedDeferredTopicFilter<TCEvent>,
+		listener: TypedListener<TCEvent>
+	): Promise<this>
+
+	once<TCEvent extends TypedContractEvent>(
+		event: TCEvent,
+		listener: TypedListener<TCEvent>
+	): Promise<this>
+	once<TCEvent extends TypedContractEvent>(
+		filter: TypedDeferredTopicFilter<TCEvent>,
+		listener: TypedListener<TCEvent>
+	): Promise<this>
+
+	listeners<TCEvent extends TypedContractEvent>(
+		event: TCEvent
+	): Promise<Array<TypedListener<TCEvent>>>
+	listeners(eventName?: string): Promise<Array<Listener>>
+	removeAllListeners<TCEvent extends TypedContractEvent>(event?: TCEvent): Promise<this>
+
+	deposit: TypedContractMethod<[], [bigint], 'payable'>
+
+	getDeposit: TypedContractMethod<[], [bigint], 'view'>
+
+	owner: TypedContractMethod<[], [string], 'view'>
+
+	withdraw: TypedContractMethod<[withdrawAmount: BigNumberish], [bigint], 'nonpayable'>
+
+	getFunction<T extends ContractMethod = ContractMethod>(key: string | FunctionFragment): T
+
+	getFunction(nameOrSignature: 'deposit'): TypedContractMethod<[], [bigint], 'payable'>
+	getFunction(nameOrSignature: 'getDeposit'): TypedContractMethod<[], [bigint], 'view'>
+	getFunction(nameOrSignature: 'owner'): TypedContractMethod<[], [string], 'view'>
+	getFunction(
+		nameOrSignature: 'withdraw'
+	): TypedContractMethod<[withdrawAmount: BigNumberish], [bigint], 'nonpayable'>
+
+	filters: {}
+}
diff --git a/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/Revert.ts b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/Revert.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ad6e23b38a65dbd4859d821c00e90f8e08efe1e0
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/Revert.ts
@@ -0,0 +1,78 @@
+/* Autogenerated file. Do not edit manually. */
+/* tslint:disable */
+/* eslint-disable */
+import type {
+	BaseContract,
+	BytesLike,
+	FunctionFragment,
+	Result,
+	Interface,
+	ContractRunner,
+	ContractMethod,
+	Listener,
+} from 'ethers'
+import type {
+	TypedContractEvent,
+	TypedDeferredTopicFilter,
+	TypedEventLog,
+	TypedListener,
+	TypedContractMethod,
+} from './common'
+
+export interface RevertInterface extends Interface {
+	getFunction(nameOrSignature: 'doRevert'): FunctionFragment
+
+	encodeFunctionData(functionFragment: 'doRevert', values?: undefined): string
+
+	decodeFunctionResult(functionFragment: 'doRevert', data: BytesLike): Result
+}
+
+export interface Revert extends BaseContract {
+	connect(runner?: ContractRunner | null): Revert
+	waitForDeployment(): Promise<this>
+
+	interface: RevertInterface
+
+	queryFilter<TCEvent extends TypedContractEvent>(
+		event: TCEvent,
+		fromBlockOrBlockhash?: string | number | undefined,
+		toBlock?: string | number | undefined
+	): Promise<Array<TypedEventLog<TCEvent>>>
+	queryFilter<TCEvent extends TypedContractEvent>(
+		filter: TypedDeferredTopicFilter<TCEvent>,
+		fromBlockOrBlockhash?: string | number | undefined,
+		toBlock?: string | number | undefined
+	): Promise<Array<TypedEventLog<TCEvent>>>
+
+	on<TCEvent extends TypedContractEvent>(
+		event: TCEvent,
+		listener: TypedListener<TCEvent>
+	): Promise<this>
+	on<TCEvent extends TypedContractEvent>(
+		filter: TypedDeferredTopicFilter<TCEvent>,
+		listener: TypedListener<TCEvent>
+	): Promise<this>
+
+	once<TCEvent extends TypedContractEvent>(
+		event: TCEvent,
+		listener: TypedListener<TCEvent>
+	): Promise<this>
+	once<TCEvent extends TypedContractEvent>(
+		filter: TypedDeferredTopicFilter<TCEvent>,
+		listener: TypedListener<TCEvent>
+	): Promise<this>
+
+	listeners<TCEvent extends TypedContractEvent>(
+		event: TCEvent
+	): Promise<Array<TypedListener<TCEvent>>>
+	listeners(eventName?: string): Promise<Array<Listener>>
+	removeAllListeners<TCEvent extends TypedContractEvent>(event?: TCEvent): Promise<this>
+
+	doRevert: TypedContractMethod<[], [void], 'nonpayable'>
+
+	getFunction<T extends ContractMethod = ContractMethod>(key: string | FunctionFragment): T
+
+	getFunction(nameOrSignature: 'doRevert'): TypedContractMethod<[], [void], 'nonpayable'>
+
+	filters: {}
+}
diff --git a/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/common.ts b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/common.ts
new file mode 100644
index 0000000000000000000000000000000000000000..247b9468ece25709be8181295f8a322d7e754fa4
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/common.ts
@@ -0,0 +1,100 @@
+/* Autogenerated file. Do not edit manually. */
+/* tslint:disable */
+/* eslint-disable */
+import type {
+	FunctionFragment,
+	Typed,
+	EventFragment,
+	ContractTransaction,
+	ContractTransactionResponse,
+	DeferredTopicFilter,
+	EventLog,
+	TransactionRequest,
+	LogDescription,
+} from 'ethers'
+
+export interface TypedDeferredTopicFilter<_TCEvent extends TypedContractEvent>
+	extends DeferredTopicFilter {}
+
+export interface TypedContractEvent<
+	InputTuple extends Array<any> = any,
+	OutputTuple extends Array<any> = any,
+	OutputObject = any,
+> {
+	(
+		...args: Partial<InputTuple>
+	): TypedDeferredTopicFilter<TypedContractEvent<InputTuple, OutputTuple, OutputObject>>
+	name: string
+	fragment: EventFragment
+	getFragment(...args: Partial<InputTuple>): EventFragment
+}
+
+type __TypechainAOutputTuple<T> = T extends TypedContractEvent<infer _U, infer W> ? W : never
+type __TypechainOutputObject<T> =
+	T extends TypedContractEvent<infer _U, infer _W, infer V> ? V : never
+
+export interface TypedEventLog<TCEvent extends TypedContractEvent> extends Omit<EventLog, 'args'> {
+	args: __TypechainAOutputTuple<TCEvent> & __TypechainOutputObject<TCEvent>
+}
+
+export interface TypedLogDescription<TCEvent extends TypedContractEvent>
+	extends Omit<LogDescription, 'args'> {
+	args: __TypechainAOutputTuple<TCEvent> & __TypechainOutputObject<TCEvent>
+}
+
+export type TypedListener<TCEvent extends TypedContractEvent> = (
+	...listenerArg: [...__TypechainAOutputTuple<TCEvent>, TypedEventLog<TCEvent>, ...undefined[]]
+) => void
+
+export type MinEthersFactory<C, ARGS> = {
+	deploy(...a: ARGS[]): Promise<C>
+}
+
+export type GetContractTypeFromFactory<F> = F extends MinEthersFactory<infer C, any> ? C : never
+export type GetARGsTypeFromFactory<F> =
+	F extends MinEthersFactory<any, any> ? Parameters<F['deploy']> : never
+
+export type StateMutability = 'nonpayable' | 'payable' | 'view'
+
+export type BaseOverrides = Omit<TransactionRequest, 'to' | 'data'>
+export type NonPayableOverrides = Omit<BaseOverrides, 'value' | 'blockTag' | 'enableCcipRead'>
+export type PayableOverrides = Omit<BaseOverrides, 'blockTag' | 'enableCcipRead'>
+export type ViewOverrides = Omit<TransactionRequest, 'to' | 'data'>
+export type Overrides<S extends StateMutability> = S extends 'nonpayable'
+	? NonPayableOverrides
+	: S extends 'payable'
+		? PayableOverrides
+		: ViewOverrides
+
+export type PostfixOverrides<A extends Array<any>, S extends StateMutability> =
+	| A
+	| [...A, Overrides<S>]
+export type ContractMethodArgs<A extends Array<any>, S extends StateMutability> = PostfixOverrides<
+	{ [I in keyof A]-?: A[I] | Typed },
+	S
+>
+
+export type DefaultReturnType<R> = R extends Array<any> ? R[0] : R
+
+// export interface ContractMethod<A extends Array<any> = Array<any>, R = any, D extends R | ContractTransactionResponse = R | ContractTransactionResponse> {
+export interface TypedContractMethod<
+	A extends Array<any> = Array<any>,
+	R = any,
+	S extends StateMutability = 'payable',
+> {
+	(
+		...args: ContractMethodArgs<A, S>
+	): S extends 'view' ? Promise<DefaultReturnType<R>> : Promise<ContractTransactionResponse>
+
+	name: string
+
+	fragment: FunctionFragment
+
+	getFragment(...args: ContractMethodArgs<A, S>): FunctionFragment
+
+	populateTransaction(...args: ContractMethodArgs<A, S>): Promise<ContractTransaction>
+	staticCall(...args: ContractMethodArgs<A, 'view'>): Promise<DefaultReturnType<R>>
+	send(...args: ContractMethodArgs<A, S>): Promise<ContractTransactionResponse>
+	estimateGas(...args: ContractMethodArgs<A, S>): Promise<bigint>
+	staticCallResult(...args: ContractMethodArgs<A, 'view'>): Promise<R>
+}
diff --git a/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/factories/Event__factory.ts b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/factories/Event__factory.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2e16b18a7ed8c5e4d37abe614ed118388ffb1be3
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/factories/Event__factory.ts
@@ -0,0 +1,51 @@
+/* Autogenerated file. Do not edit manually. */
+/* tslint:disable */
+/* eslint-disable */
+
+import { Contract, Interface, type ContractRunner } from 'ethers'
+import type { Event, EventInterface } from '../Event'
+
+const _abi = [
+	{
+		anonymous: false,
+		inputs: [
+			{
+				indexed: true,
+				internalType: 'address',
+				name: 'sender',
+				type: 'address',
+			},
+			{
+				indexed: false,
+				internalType: 'uint256',
+				name: 'value',
+				type: 'uint256',
+			},
+			{
+				indexed: false,
+				internalType: 'string',
+				name: 'message',
+				type: 'string',
+			},
+		],
+		name: 'ExampleEvent',
+		type: 'event',
+	},
+	{
+		inputs: [],
+		name: 'triggerEvent',
+		outputs: [],
+		stateMutability: 'nonpayable',
+		type: 'function',
+	},
+] as const
+
+export class Event__factory {
+	static readonly abi = _abi
+	static createInterface(): EventInterface {
+		return new Interface(_abi) as EventInterface
+	}
+	static connect(address: string, runner?: ContractRunner | null): Event {
+		return new Contract(address, _abi, runner) as unknown as Event
+	}
+}
diff --git a/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/factories/PiggyBank__factory.ts b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/factories/PiggyBank__factory.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0efea80ed2dc88c637bacd0eb9dda91858426a23
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/factories/PiggyBank__factory.ts
@@ -0,0 +1,82 @@
+/* Autogenerated file. Do not edit manually. */
+/* tslint:disable */
+/* eslint-disable */
+
+import { Contract, Interface, type ContractRunner } from 'ethers'
+import type { PiggyBank, PiggyBankInterface } from '../PiggyBank'
+
+const _abi = [
+	{
+		inputs: [],
+		stateMutability: 'nonpayable',
+		type: 'constructor',
+	},
+	{
+		inputs: [],
+		name: 'deposit',
+		outputs: [
+			{
+				internalType: 'uint256',
+				name: '',
+				type: 'uint256',
+			},
+		],
+		stateMutability: 'payable',
+		type: 'function',
+	},
+	{
+		inputs: [],
+		name: 'getDeposit',
+		outputs: [
+			{
+				internalType: 'uint256',
+				name: '',
+				type: 'uint256',
+			},
+		],
+		stateMutability: 'view',
+		type: 'function',
+	},
+	{
+		inputs: [],
+		name: 'owner',
+		outputs: [
+			{
+				internalType: 'address',
+				name: '',
+				type: 'address',
+			},
+		],
+		stateMutability: 'view',
+		type: 'function',
+	},
+	{
+		inputs: [
+			{
+				internalType: 'uint256',
+				name: 'withdrawAmount',
+				type: 'uint256',
+			},
+		],
+		name: 'withdraw',
+		outputs: [
+			{
+				internalType: 'uint256',
+				name: 'remainingBal',
+				type: 'uint256',
+			},
+		],
+		stateMutability: 'nonpayable',
+		type: 'function',
+	},
+] as const
+
+export class PiggyBank__factory {
+	static readonly abi = _abi
+	static createInterface(): PiggyBankInterface {
+		return new Interface(_abi) as PiggyBankInterface
+	}
+	static connect(address: string, runner?: ContractRunner | null): PiggyBank {
+		return new Contract(address, _abi, runner) as unknown as PiggyBank
+	}
+}
diff --git a/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/factories/Revert__factory.ts b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/factories/Revert__factory.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ece1c6b5426ef7e31547d3cd736b06248d603746
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/factories/Revert__factory.ts
@@ -0,0 +1,31 @@
+/* Autogenerated file. Do not edit manually. */
+/* tslint:disable */
+/* eslint-disable */
+
+import { Contract, Interface, type ContractRunner } from 'ethers'
+import type { Revert, RevertInterface } from '../Revert'
+
+const _abi = [
+	{
+		inputs: [],
+		stateMutability: 'nonpayable',
+		type: 'constructor',
+	},
+	{
+		inputs: [],
+		name: 'doRevert',
+		outputs: [],
+		stateMutability: 'nonpayable',
+		type: 'function',
+	},
+] as const
+
+export class Revert__factory {
+	static readonly abi = _abi
+	static createInterface(): RevertInterface {
+		return new Interface(_abi) as RevertInterface
+	}
+	static connect(address: string, runner?: ContractRunner | null): Revert {
+		return new Contract(address, _abi, runner) as unknown as Revert
+	}
+}
diff --git a/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/factories/index.ts b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/factories/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..67370dba411c3d9e5908cccdbee1a858944258f5
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/factories/index.ts
@@ -0,0 +1,6 @@
+/* Autogenerated file. Do not edit manually. */
+/* tslint:disable */
+/* eslint-disable */
+export { Event__factory } from './Event__factory'
+export { PiggyBank__factory } from './PiggyBank__factory'
+export { Revert__factory } from './Revert__factory'
diff --git a/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/index.ts b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3e324e80dcb1c04a0a34c2abaaad2afbec620278
--- /dev/null
+++ b/substrate/frame/revive/rpc/examples/js/types/ethers-contracts/index.ts
@@ -0,0 +1,10 @@
+/* Autogenerated file. Do not edit manually. */
+/* tslint:disable */
+/* eslint-disable */
+export type { Event } from './Event'
+export type { PiggyBank } from './PiggyBank'
+export type { Revert } from './Revert'
+export * as factories from './factories'
+export { Event__factory } from './factories/Event__factory'
+export { PiggyBank__factory } from './factories/PiggyBank__factory'
+export { Revert__factory } from './factories/Revert__factory'
diff --git a/substrate/frame/revive/rpc/examples/package.json b/substrate/frame/revive/rpc/examples/package.json
deleted file mode 100644
index 37d819aaa481a93a18b269d2b9d6479749768dfe..0000000000000000000000000000000000000000
--- a/substrate/frame/revive/rpc/examples/package.json
+++ /dev/null
@@ -1 +0,0 @@
-{ "dependencies": { "@parity/revive": "^0.0.5" } }
\ No newline at end of file
diff --git a/substrate/frame/revive/rpc/revive_chain.metadata b/substrate/frame/revive/rpc/revive_chain.metadata
index e5bfa0820b100bce59107541915f9352fce1c99a..3560b3b90407acce7f602ce91ac089843be8dea8 100644
Binary files a/substrate/frame/revive/rpc/revive_chain.metadata and b/substrate/frame/revive/rpc/revive_chain.metadata differ
diff --git a/substrate/frame/revive/rpc/src/client.rs b/substrate/frame/revive/rpc/src/client.rs
index b7efae15c4aa153d60a4068bb64d4844b30c340e..1ca1a6d37c534bdd9d05bbdac7cbb33fdfe5feb6 100644
--- a/substrate/frame/revive/rpc/src/client.rs
+++ b/substrate/frame/revive/rpc/src/client.rs
@@ -236,7 +236,6 @@ struct ClientInner {
 	cache: Shared<BlockCache<CACHE_SIZE>>,
 	chain_id: u64,
 	max_block_weight: Weight,
-	native_to_evm_ratio: U256,
 }
 
 impl ClientInner {
@@ -252,20 +251,10 @@ impl ClientInner {
 
 		let rpc = LegacyRpcMethods::<SrcChainConfig>::new(RpcClient::new(rpc_client.clone()));
 
-		let (native_to_evm_ratio, chain_id, max_block_weight) =
-			tokio::try_join!(native_to_evm_ratio(&api), chain_id(&api), max_block_weight(&api))?;
+		let (chain_id, max_block_weight) =
+			tokio::try_join!(chain_id(&api), max_block_weight(&api))?;
 
-		Ok(Self { api, rpc_client, rpc, cache, chain_id, max_block_weight, native_to_evm_ratio })
-	}
-
-	/// Convert a native balance to an EVM balance.
-	fn native_to_evm_decimals(&self, value: U256) -> U256 {
-		value.saturating_mul(self.native_to_evm_ratio)
-	}
-
-	/// Convert an evm balance to a native balance.
-	fn evm_to_native_decimals(&self, value: U256) -> U256 {
-		value / self.native_to_evm_ratio
+		Ok(Self { api, rpc_client, rpc, cache, chain_id, max_block_weight })
 	}
 
 	/// Get the receipt infos from the extrinsics in a block.
@@ -368,13 +357,6 @@ async fn max_block_weight(api: &OnlineClient<SrcChainConfig>) -> Result<Weight,
 	Ok(max_block.0)
 }
 
-/// Fetch the native to EVM ratio from the substrate chain.
-async fn native_to_evm_ratio(api: &OnlineClient<SrcChainConfig>) -> Result<U256, ClientError> {
-	let query = subxt_client::constants().revive().native_to_eth_ratio();
-	let ratio = api.constants().at(&query)?;
-	Ok(U256::from(ratio))
-}
-
 /// Extract the block timestamp.
 async fn extract_block_timestamp(block: &SubstrateBlock) -> Option<u64> {
 	let extrinsics = block.extrinsics().await.ok()?;
@@ -607,8 +589,9 @@ impl Client {
 
 		let runtime_api = self.runtime_api(at).await?;
 		let payload = subxt_client::apis().revive_api().balance(address);
-		let balance = runtime_api.call(payload).await?.into();
-		Ok(self.inner.native_to_evm_decimals(balance))
+		let balance = runtime_api.call(payload).await?;
+
+		Ok(*balance)
 	}
 
 	/// Get the contract storage for the given contract address and key.
@@ -659,13 +642,8 @@ impl Client {
 	) -> Result<EthContractResult<Balance, Vec<u8>>, ClientError> {
 		let runtime_api = self.runtime_api(&block).await?;
 
-		let value = self
-			.inner
-			.evm_to_native_decimals(tx.value.unwrap_or_default())
-			.try_into()
-			.map_err(|_| ClientError::ConversionFailed)?;
-
 		// TODO: remove once subxt is updated
+		let value = subxt::utils::Static(tx.value.unwrap_or_default());
 		let from = tx.from.map(|v| v.0.into());
 		let to = tx.to.map(|v| v.0.into());
 
diff --git a/substrate/frame/revive/rpc/src/example.rs b/substrate/frame/revive/rpc/src/example.rs
index d2f9b509f4d21000c1d5f359551804a89eb4321e..20f00465b146f1a5ecf4a3882969dd2f429e9b92 100644
--- a/substrate/frame/revive/rpc/src/example.rs
+++ b/substrate/frame/revive/rpc/src/example.rs
@@ -105,6 +105,30 @@ impl TransactionBuilder {
 		self
 	}
 
+	/// Call eth_call to get the result of a view function
+	pub async fn eth_call(
+		self,
+		client: &(impl EthRpcClient + Send + Sync),
+	) -> anyhow::Result<Vec<u8>> {
+		let TransactionBuilder { signer, value, input, to, .. } = self;
+
+		let from = signer.address();
+		let result = client
+			.call(
+				GenericTransaction {
+					from: Some(from),
+					input: Some(input.clone()),
+					value: Some(value),
+					to,
+					..Default::default()
+				},
+				None,
+			)
+			.await
+			.with_context(|| "eth_call failed")?;
+		Ok(result.0)
+	}
+
 	/// Send the transaction.
 	pub async fn send(self, client: &(impl EthRpcClient + Send + Sync)) -> anyhow::Result<H256> {
 		let TransactionBuilder { signer, value, input, to, mutate } = self;
@@ -156,6 +180,7 @@ impl TransactionBuilder {
 		Ok(hash)
 	}
 
+	/// Send the transaction and wait for the receipt.
 	pub async fn send_and_wait_for_receipt(
 		self,
 		client: &(impl EthRpcClient + Send + Sync),
diff --git a/substrate/frame/revive/rpc/src/subxt_client.rs b/substrate/frame/revive/rpc/src/subxt_client.rs
index 11a0d51ed03efd032de1122882eb8a453457c480..a232b231bc7c0337c71e7e45de462573ffc63e25 100644
--- a/substrate/frame/revive/rpc/src/subxt_client.rs
+++ b/substrate/frame/revive/rpc/src/subxt_client.rs
@@ -21,6 +21,11 @@ use subxt::config::{signed_extensions, Config, PolkadotConfig};
 
 #[subxt::subxt(
 	runtime_metadata_path = "revive_chain.metadata",
+	// TODO remove once subxt use the same U256 type
+	substitute_type(
+		path = "primitive_types::U256",
+		with = "::subxt::utils::Static<::sp_core::U256>"
+	),
 	substitute_type(
 		path = "pallet_revive::primitives::EthContractResult<A, B>",
 		with = "::subxt::utils::Static<::pallet_revive::EthContractResult<A, B>>"
diff --git a/substrate/frame/revive/rpc/src/tests.rs b/substrate/frame/revive/rpc/src/tests.rs
index 3d2cbe42be8ee088af20c3ffc34066e70c443e88..eb23bd7583a092165ab2d621d2ba3eaa8db770a4 100644
--- a/substrate/frame/revive/rpc/src/tests.rs
+++ b/substrate/frame/revive/rpc/src/tests.rs
@@ -22,6 +22,7 @@ use crate::{
 	EthRpcClient,
 };
 use clap::Parser;
+use ethabi::Token;
 use jsonrpsee::ws_client::{WsClient, WsClientBuilder};
 use pallet_revive::{
 	create1,
@@ -48,15 +49,12 @@ async fn ws_client_with_retry(url: &str) -> WsClient {
 }
 
 fn get_contract(name: &str) -> anyhow::Result<(Vec<u8>, ethabi::Contract)> {
-	const PVM_CONTRACTS: &str = include_str!("../examples/js/pvm-contracts.json");
-	let pvm_contract: serde_json::Value = serde_json::from_str(PVM_CONTRACTS)?;
-	let pvm_contract = pvm_contract[name].as_object().unwrap();
-	let bytecode = pvm_contract["bytecode"].as_str().unwrap();
-	let bytecode = hex::decode(bytecode)?;
+	let pvm_dir: std::path::PathBuf = "./examples/js/pvm".into();
+	let abi_dir: std::path::PathBuf = "./examples/js/abi".into();
+	let bytecode = std::fs::read(pvm_dir.join(format!("{}.polkavm", name)))?;
 
-	let abi = pvm_contract["abi"].clone();
-	let abi = serde_json::to_string(&abi)?;
-	let contract = ethabi::Contract::load(abi.as_bytes())?;
+	let abi = std::fs::read(abi_dir.join(format!("{}.json", name)))?;
+	let contract = ethabi::Contract::load(abi.as_slice())?;
 
 	Ok((bytecode, contract))
 }
@@ -280,3 +278,44 @@ async fn invalid_transaction() -> anyhow::Result<()> {
 
 	Ok(())
 }
+
+#[tokio::test]
+async fn native_evm_ratio_works() -> anyhow::Result<()> {
+	let _lock = SHARED_RESOURCES.write();
+	let client = SharedResources::client().await;
+	let (bytecode, contract) = get_contract("piggyBank")?;
+	let contract_address = TransactionBuilder::default()
+		.input(bytecode)
+		.send_and_wait_for_receipt(&client)
+		.await?
+		.contract_address
+		.unwrap();
+
+	let value = 10_000_000_000_000_000_000u128; // 10 eth
+	TransactionBuilder::default()
+		.to(contract_address)
+		.input(contract.function("deposit")?.encode_input(&[])?.to_vec())
+		.value(value.into())
+		.send_and_wait_for_receipt(&client)
+		.await?;
+
+	let contract_value = client.get_balance(contract_address, BlockTag::Latest.into()).await?;
+	assert_eq!(contract_value, value.into());
+
+	let withdraw_value = 1_000_000_000_000_000_000u128; // 1 eth
+	TransactionBuilder::default()
+		.to(contract_address)
+		.input(
+			contract
+				.function("withdraw")?
+				.encode_input(&[Token::Uint(withdraw_value.into())])?
+				.to_vec(),
+		)
+		.send_and_wait_for_receipt(&client)
+		.await?;
+
+	let contract_value = client.get_balance(contract_address, BlockTag::Latest.into()).await?;
+	assert_eq!(contract_value, (value - withdraw_value).into());
+
+	Ok(())
+}
diff --git a/substrate/frame/revive/src/benchmarking/mod.rs b/substrate/frame/revive/src/benchmarking/mod.rs
index 593c16cbb2d8d67290f6de6d0b2888a9fae5e042..40ad3a3aed179018ef29238599e82ad305703810 100644
--- a/substrate/frame/revive/src/benchmarking/mod.rs
+++ b/substrate/frame/revive/src/benchmarking/mod.rs
@@ -1516,7 +1516,7 @@ mod benchmarks {
 		let callee_bytes = callee.encode();
 		let callee_len = callee_bytes.len() as u32;
 
-		let value: BalanceOf<T> = t.into();
+		let value: BalanceOf<T> = (1_000_000 * t).into();
 		let value_bytes = Into::<U256>::into(value).encode();
 
 		let deposit: BalanceOf<T> = (u32::MAX - 100).into();
@@ -1591,7 +1591,7 @@ mod benchmarks {
 		let hash_bytes = hash.encode();
 		let hash_len = hash_bytes.len() as u32;
 
-		let value: BalanceOf<T> = 1u32.into();
+		let value: BalanceOf<T> = 1_000_000u32.into();
 		let value_bytes = Into::<U256>::into(value).encode();
 		let value_len = value_bytes.len() as u32;
 
@@ -1645,7 +1645,10 @@ mod benchmarks {
 
 		assert_ok!(result);
 		assert!(ContractInfoOf::<T>::get(&addr).is_some());
-		assert_eq!(T::Currency::balance(&account_id), Pallet::<T>::min_balance() + value);
+		assert_eq!(
+			T::Currency::balance(&account_id),
+			Pallet::<T>::min_balance() + Pallet::<T>::convert_evm_to_native(value.into()).unwrap()
+		);
 		Ok(())
 	}
 
diff --git a/substrate/frame/revive/src/evm/runtime.rs b/substrate/frame/revive/src/evm/runtime.rs
index c27edac935008e0997b33bf1f796b95ac644a6cb..21294fdf6baa117f085494e4819b55deb3d4a147 100644
--- a/substrate/frame/revive/src/evm/runtime.rs
+++ b/substrate/frame/revive/src/evm/runtime.rs
@@ -313,9 +313,10 @@ pub trait EthExtra {
 			return Err(InvalidTransaction::Call);
 		}
 
-		let value = (value / U256::from(<Self::Config as crate::Config>::NativeToEthRatio::get()))
-			.try_into()
-			.map_err(|_| InvalidTransaction::Call)?;
+		let value = crate::Pallet::<Self::Config>::convert_evm_to_native(value).map_err(|err| {
+			log::debug!(target: LOG_TARGET, "Failed to convert value to native: {err:?}");
+			InvalidTransaction::Call
+		})?;
 
 		let call = if let Some(dest) = to {
 			crate::Call::call::<Self::Config> {
diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs
index 4f90b41b0de549b4103edc7eea8868b6b51dc853..fdb45f045bbc0885a2f7e35017e0e32872def97a 100644
--- a/substrate/frame/revive/src/exec.rs
+++ b/substrate/frame/revive/src/exec.rs
@@ -569,8 +569,8 @@ struct Frame<T: Config> {
 	account_id: T::AccountId,
 	/// The cached in-storage data of the contract.
 	contract_info: CachedContract<T>,
-	/// The amount of balance transferred by the caller as part of the call.
-	value_transferred: BalanceOf<T>,
+	/// The EVM balance transferred by the caller as part of the call.
+	value_transferred: U256,
 	/// Determines whether this is a call or instantiate frame.
 	entry_point: ExportedFunction,
 	/// The gas meter capped to the supplied gas limit.
@@ -757,7 +757,7 @@ where
 		dest: H160,
 		gas_meter: &'a mut GasMeter<T>,
 		storage_meter: &'a mut storage::meter::Meter<T>,
-		value: BalanceOf<T>,
+		value: U256,
 		input_data: Vec<u8>,
 		debug_message: Option<&'a mut DebugBuffer>,
 	) -> ExecResult {
@@ -791,7 +791,7 @@ where
 		executable: E,
 		gas_meter: &'a mut GasMeter<T>,
 		storage_meter: &'a mut storage::meter::Meter<T>,
-		value: BalanceOf<T>,
+		value: U256,
 		input_data: Vec<u8>,
 		salt: Option<&[u8; 32]>,
 		debug_message: Option<&'a mut DebugBuffer>,
@@ -834,7 +834,7 @@ where
 			origin,
 			gas_meter,
 			storage_meter,
-			value,
+			value.into(),
 			debug_message,
 		)
 		.unwrap()
@@ -843,14 +843,14 @@ where
 
 	/// Create a new call stack.
 	///
-	/// Returns `None` when calling a non existant contract. This is not an error case
+	/// Returns `None` when calling a non existent contract. This is not an error case
 	/// since this will result in a value transfer.
 	fn new(
 		args: FrameArgs<T, E>,
 		origin: Origin<T>,
 		gas_meter: &'a mut GasMeter<T>,
 		storage_meter: &'a mut storage::meter::Meter<T>,
-		value: BalanceOf<T>,
+		value: U256,
 		debug_message: Option<&'a mut DebugBuffer>,
 	) -> Result<Option<(Self, E)>, ExecError> {
 		origin.ensure_mapped()?;
@@ -890,7 +890,7 @@ where
 	/// not initialized, yet.
 	fn new_frame<S: storage::meter::State + Default + Debug>(
 		frame_args: FrameArgs<T, E>,
-		value_transferred: BalanceOf<T>,
+		value_transferred: U256,
 		gas_meter: &mut GasMeter<T>,
 		gas_limit: Weight,
 		storage_meter: &mut storage::meter::GenericMeter<T, S>,
@@ -975,7 +975,7 @@ where
 	fn push_frame(
 		&mut self,
 		frame_args: FrameArgs<T, E>,
-		value_transferred: BalanceOf<T>,
+		value_transferred: U256,
 		gas_limit: Weight,
 		deposit_limit: BalanceOf<T>,
 		read_only: bool,
@@ -1282,8 +1282,9 @@ where
 		origin: &Origin<T>,
 		from: &T::AccountId,
 		to: &T::AccountId,
-		value: BalanceOf<T>,
+		value: U256,
 	) -> ExecResult {
+		let value = crate::Pallet::<T>::convert_evm_to_native(value)?;
 		if value.is_zero() {
 			return Ok(Default::default());
 		}
@@ -1311,7 +1312,7 @@ where
 		origin: &Origin<T>,
 		from: &Origin<T>,
 		to: &T::AccountId,
-		value: BalanceOf<T>,
+		value: U256,
 	) -> ExecResult {
 		// If the from address is root there is no account to transfer from, and therefore we can't
 		// take any `value` other than 0.
@@ -1358,7 +1359,11 @@ where
 
 	/// Returns the *free* balance of the supplied AccountId.
 	fn account_balance(&self, who: &T::AccountId) -> U256 {
-		T::Currency::reducible_balance(who, Preservation::Preserve, Fortitude::Polite).into()
+		crate::Pallet::<T>::convert_native_to_evm(T::Currency::reducible_balance(
+			who,
+			Preservation::Preserve,
+			Fortitude::Polite,
+		))
 	}
 
 	/// Certain APIs, e.g. `{set,get}_immutable_data` behave differently depending
@@ -2066,7 +2071,7 @@ mod tests {
 					BOB_ADDR,
 					&mut gas_meter,
 					&mut storage_meter,
-					value,
+					value.into(),
 					vec![],
 					None,
 				),
@@ -2086,7 +2091,7 @@ mod tests {
 			set_balance(&BOB, 0);
 
 			let origin = Origin::from_account_id(ALICE);
-			MockStack::transfer(&origin, &ALICE, &BOB, 55).unwrap();
+			MockStack::transfer(&origin, &ALICE, &BOB, 55u64.into()).unwrap();
 
 			let min_balance = <Test as Config>::Currency::minimum_balance();
 			assert_eq!(get_balance(&ALICE), 45 - min_balance);
@@ -2107,7 +2112,12 @@ mod tests {
 			set_balance(&ALICE, ed * 2);
 			set_balance(&BOB, ed + value);
 
-			assert_ok!(MockStack::transfer(&Origin::from_account_id(ALICE), &BOB, &CHARLIE, value));
+			assert_ok!(MockStack::transfer(
+				&Origin::from_account_id(ALICE),
+				&BOB,
+				&CHARLIE,
+				value.into()
+			));
 			assert_eq!(get_balance(&ALICE), ed);
 			assert_eq!(get_balance(&BOB), ed);
 			assert_eq!(get_balance(&CHARLIE), ed + value);
@@ -2116,7 +2126,7 @@ mod tests {
 			set_balance(&ALICE, ed);
 			set_balance(&BOB, ed + value);
 			assert_err!(
-				MockStack::transfer(&Origin::from_account_id(ALICE), &BOB, &DJANGO, value),
+				MockStack::transfer(&Origin::from_account_id(ALICE), &BOB, &DJANGO, value.into()),
 				<Error<Test>>::TransferFailed
 			);
 
@@ -2124,7 +2134,7 @@ mod tests {
 			set_balance(&ALICE, ed * 2);
 			set_balance(&BOB, value);
 			assert_err!(
-				MockStack::transfer(&Origin::from_account_id(ALICE), &BOB, &EVE, value),
+				MockStack::transfer(&Origin::from_account_id(ALICE), &BOB, &EVE, value.into()),
 				<Error<Test>>::TransferFailed
 			);
 			// The ED transfer would work. But it should only be executed with the actual transfer
@@ -2153,7 +2163,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				value,
+				value.into(),
 				vec![],
 				None,
 			)
@@ -2191,7 +2201,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				value,
+				value.into(),
 				vec![],
 				None,
 			)
@@ -2223,7 +2233,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				55,
+				55u64.into(),
 				vec![],
 				None,
 			)
@@ -2246,7 +2256,7 @@ mod tests {
 		ExtBuilder::default().build().execute_with(|| {
 			set_balance(&from, 0);
 
-			let result = MockStack::transfer(&origin, &from, &dest, 100);
+			let result = MockStack::transfer(&origin, &from, &dest, 100u64.into());
 
 			assert_eq!(result, Err(Error::<Test>::TransferFailed.into()));
 			assert_eq!(get_balance(&from), 0);
@@ -2272,7 +2282,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			);
@@ -2301,7 +2311,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			);
@@ -2330,7 +2340,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![1, 2, 3, 4],
 				None,
 			);
@@ -2365,7 +2375,7 @@ mod tests {
 					executable,
 					&mut gas_meter,
 					&mut storage_meter,
-					min_balance,
+					min_balance.into(),
 					vec![1, 2, 3, 4],
 					Some(&[0; 32]),
 					None,
@@ -2420,7 +2430,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				value,
+				value.into(),
 				vec![],
 				None,
 			);
@@ -2484,7 +2494,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			);
@@ -2549,7 +2559,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			);
@@ -2581,7 +2591,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			);
@@ -2618,7 +2628,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![0],
 				None,
 			);
@@ -2644,7 +2654,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![0],
 				None,
 			);
@@ -2688,7 +2698,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![0],
 				None,
 			);
@@ -2714,7 +2724,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![0],
 				None,
 			);
@@ -2740,7 +2750,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				1,
+				1u64.into(),
 				vec![0],
 				None,
 			);
@@ -2784,7 +2794,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![0],
 				None,
 			);
@@ -2829,7 +2839,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			);
@@ -2854,7 +2864,7 @@ mod tests {
 					executable,
 					&mut gas_meter,
 					&mut storage_meter,
-					0, // <- zero value
+					U256::zero(), // <- zero value
 					vec![],
 					Some(&[0; 32]),
 					None,
@@ -2889,8 +2899,7 @@ mod tests {
 						executable,
 						&mut gas_meter,
 						&mut storage_meter,
-
-						min_balance,
+						min_balance.into(),
 						vec![],
 						Some(&[0 ;32]),
 						None,
@@ -2945,7 +2954,7 @@ mod tests {
 						&mut gas_meter,
 						&mut storage_meter,
 
-						min_balance,
+						min_balance.into(),
 						vec![],
 						Some(&[0; 32]),
 						None,
@@ -3010,7 +3019,7 @@ mod tests {
 						BOB_ADDR,
 						&mut GasMeter::<Test>::new(GAS_LIMIT),
 						&mut storage_meter,
-						min_balance * 10,
+						(min_balance * 10).into(),
 						vec![],
 						None,
 					),
@@ -3090,7 +3099,7 @@ mod tests {
 						BOB_ADDR,
 						&mut GasMeter::<Test>::new(GAS_LIMIT),
 						&mut storage_meter,
-						0,
+						U256::zero(),
 						vec![],
 						None,
 					),
@@ -3132,7 +3141,7 @@ mod tests {
 						executable,
 						&mut gas_meter,
 						&mut storage_meter,
-						100,
+						100u64.into(),
 						vec![],
 						Some(&[0; 32]),
 						None,
@@ -3197,7 +3206,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![0],
 				None,
 			);
@@ -3258,7 +3267,7 @@ mod tests {
 					executable,
 					&mut gas_meter,
 					&mut storage_meter,
-					10,
+					10u64.into(),
 					vec![],
 					Some(&[0; 32]),
 					None,
@@ -3305,7 +3314,7 @@ mod tests {
 					BOB_ADDR,
 					&mut gas_meter,
 					&mut storage_meter,
-					0,
+					U256::zero(),
 					vec![],
 					None,
 				)
@@ -3336,7 +3345,7 @@ mod tests {
 				BOB_ADDR,
 				&mut gas_meter,
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				Some(&mut debug_buffer),
 			)
@@ -3369,7 +3378,7 @@ mod tests {
 				BOB_ADDR,
 				&mut gas_meter,
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				Some(&mut debug_buffer),
 			);
@@ -3402,7 +3411,7 @@ mod tests {
 				BOB_ADDR,
 				&mut gas_meter,
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				Some(&mut debug_buf_after),
 			)
@@ -3435,7 +3444,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				CHARLIE_ADDR.as_bytes().to_vec(),
 				None,
 			));
@@ -3447,7 +3456,7 @@ mod tests {
 					BOB_ADDR,
 					&mut GasMeter::<Test>::new(GAS_LIMIT),
 					&mut storage_meter,
-					0,
+					U256::zero(),
 					BOB_ADDR.as_bytes().to_vec(),
 					None,
 				)
@@ -3497,7 +3506,7 @@ mod tests {
 					BOB_ADDR,
 					&mut GasMeter::<Test>::new(GAS_LIMIT),
 					&mut storage_meter,
-					0,
+					U256::zero(),
 					vec![0],
 					None,
 				)
@@ -3531,7 +3540,7 @@ mod tests {
 				BOB_ADDR,
 				&mut gas_meter,
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			)
@@ -3615,7 +3624,7 @@ mod tests {
 				BOB_ADDR,
 				&mut gas_meter,
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			)
@@ -3740,7 +3749,7 @@ mod tests {
 					fail_executable,
 					&mut gas_meter,
 					&mut storage_meter,
-					min_balance * 100,
+					(min_balance * 100).into(),
 					vec![],
 					Some(&[0; 32]),
 					None,
@@ -3753,7 +3762,7 @@ mod tests {
 					success_executable,
 					&mut gas_meter,
 					&mut storage_meter,
-					min_balance * 100,
+					(min_balance * 100).into(),
 					vec![],
 					Some(&[0; 32]),
 					None,
@@ -3765,7 +3774,7 @@ mod tests {
 					succ_fail_executable,
 					&mut gas_meter,
 					&mut storage_meter,
-					min_balance * 200,
+					(min_balance * 200).into(),
 					vec![],
 					Some(&[0; 32]),
 					None,
@@ -3777,7 +3786,7 @@ mod tests {
 					succ_succ_executable,
 					&mut gas_meter,
 					&mut storage_meter,
-					min_balance * 200,
+					(min_balance * 200).into(),
 					vec![],
 					Some(&[0; 32]),
 					None,
@@ -3846,7 +3855,7 @@ mod tests {
 				BOB_ADDR,
 				&mut gas_meter,
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			));
@@ -3957,7 +3966,7 @@ mod tests {
 				BOB_ADDR,
 				&mut gas_meter,
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			));
@@ -3996,7 +4005,7 @@ mod tests {
 				BOB_ADDR,
 				&mut gas_meter,
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			));
@@ -4035,7 +4044,7 @@ mod tests {
 				BOB_ADDR,
 				&mut gas_meter,
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			));
@@ -4088,7 +4097,7 @@ mod tests {
 				BOB_ADDR,
 				&mut gas_meter,
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			));
@@ -4144,7 +4153,7 @@ mod tests {
 				BOB_ADDR,
 				&mut gas_meter,
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			));
@@ -4219,7 +4228,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			));
@@ -4289,7 +4298,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![0],
 				None,
 			);
@@ -4327,7 +4336,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			));
@@ -4389,7 +4398,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![0],
 				None,
 			);
@@ -4422,7 +4431,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			);
@@ -4505,7 +4514,7 @@ mod tests {
 					BOB_ADDR,
 					&mut GasMeter::<Test>::new(GAS_LIMIT),
 					&mut storage_meter,
-					0,
+					U256::zero(),
 					vec![],
 					None,
 				)
@@ -4573,7 +4582,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![0],
 				None,
 			);
@@ -4639,7 +4648,7 @@ mod tests {
 				BOB_ADDR,
 				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&mut storage_meter,
-				0,
+				U256::zero(),
 				vec![],
 				None,
 			);
@@ -4690,7 +4699,7 @@ mod tests {
 					BOB_ADDR,
 					&mut GasMeter::<Test>::new(GAS_LIMIT),
 					&mut storage_meter,
-					0,
+					U256::zero(),
 					vec![],
 					None,
 				)
@@ -4761,7 +4770,7 @@ mod tests {
 					BOB_ADDR,
 					&mut GasMeter::<Test>::new(GAS_LIMIT),
 					&mut storage_meter,
-					0,
+					U256::zero(),
 					vec![],
 					None,
 				)
@@ -4807,7 +4816,7 @@ mod tests {
 					BOB_ADDR,
 					&mut GasMeter::<Test>::new(GAS_LIMIT),
 					&mut storage_meter,
-					0,
+					U256::zero(),
 					vec![],
 					None,
 				)
@@ -4851,7 +4860,7 @@ mod tests {
 					BOB_ADDR,
 					&mut GasMeter::<Test>::new(GAS_LIMIT),
 					&mut storage_meter,
-					0,
+					U256::zero(),
 					vec![],
 					None,
 				)
@@ -4906,7 +4915,7 @@ mod tests {
 					BOB_ADDR,
 					&mut GasMeter::<Test>::new(GAS_LIMIT),
 					&mut storage_meter,
-					0,
+					U256::zero(),
 					vec![0],
 					None,
 				),
diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs
index 5ca0042d929bafce0ca34c6377e0f99c0e5dbdd0..caecf07c4071acd59288009efa0332da5fd613c0 100644
--- a/substrate/frame/revive/src/lib.rs
+++ b/substrate/frame/revive/src/lib.rs
@@ -59,6 +59,7 @@ use frame_support::{
 	pallet_prelude::DispatchClass,
 	traits::{
 		fungible::{Inspect, Mutate, MutateHold},
+		tokens::{Fortitude::Polite, Preservation::Preserve},
 		ConstU32, ConstU64, Contains, EnsureOrigin, Get, IsType, OriginTrait, Time,
 	},
 	weights::{Weight, WeightMeter},
@@ -73,7 +74,7 @@ use pallet_transaction_payment::OnChargeTransaction;
 use scale_info::TypeInfo;
 use sp_core::{H160, H256, U256};
 use sp_runtime::{
-	traits::{BadOrigin, Convert, Dispatchable, Saturating},
+	traits::{BadOrigin, Convert, Dispatchable, Saturating, Zero},
 	DispatchError,
 };
 
@@ -379,7 +380,7 @@ pub mod pallet {
 			type RuntimeMemory = ConstU32<{ 128 * 1024 * 1024 }>;
 			type PVFMemory = ConstU32<{ 512 * 1024 * 1024 }>;
 			type ChainId = ConstU64<0>;
-			type NativeToEthRatio = ConstU32<1_000_000>;
+			type NativeToEthRatio = ConstU32<1>;
 		}
 	}
 
@@ -561,6 +562,8 @@ pub mod pallet {
 		ExecutionFailed,
 		/// Failed to convert a U256 to a Balance.
 		BalanceConversionFailed,
+		/// Failed to convert an EVM balance to a native balance.
+		DecimalPrecisionLoss,
 		/// Immutable data can only be set during deploys and only be read during calls.
 		/// Additionally, it is only valid to set the data once and it must not be empty.
 		InvalidImmutableAccess,
@@ -1115,7 +1118,7 @@ where
 				dest,
 				&mut gas_meter,
 				&mut storage_meter,
-				value,
+				Self::convert_native_to_evm(value),
 				data,
 				debug_message.as_mut(),
 			)?;
@@ -1180,7 +1183,7 @@ where
 				executable,
 				&mut gas_meter,
 				&mut storage_meter,
-				value,
+				Self::convert_native_to_evm(value),
 				data,
 				salt.as_ref(),
 				debug_message.as_mut(),
@@ -1214,7 +1217,7 @@ where
 	///
 	/// - `origin`: The origin of the call.
 	/// - `dest`: The destination address of the call.
-	/// - `value`: The value to transfer.
+	/// - `value`: The EVM value to transfer.
 	/// - `input`: The input data.
 	/// - `gas_limit`: The gas limit enforced during contract execution.
 	/// - `storage_deposit_limit`: The maximum balance that can be charged to the caller for storage
@@ -1226,7 +1229,7 @@ where
 	pub fn bare_eth_transact(
 		origin: T::AccountId,
 		dest: Option<H160>,
-		value: BalanceOf<T>,
+		value: U256,
 		input: Vec<u8>,
 		gas_limit: Weight,
 		storage_deposit_limit: BalanceOf<T>,
@@ -1250,6 +1253,18 @@ where
 		// Get the nonce to encode in the tx.
 		let nonce: T::Nonce = <System<T>>::account_nonce(&origin);
 
+		// Convert the value to the native balance type.
+		let native_value = match Self::convert_evm_to_native(value) {
+			Ok(v) => v,
+			Err(err) =>
+				return EthContractResult {
+					gas_required: Default::default(),
+					storage_deposit: Default::default(),
+					fee: Default::default(),
+					result: Err(err.into()),
+				},
+		};
+
 		// Dry run the call
 		let (mut result, dispatch_info) = match dest {
 			// A contract call.
@@ -1258,13 +1273,14 @@ where
 				let result = crate::Pallet::<T>::bare_call(
 					T::RuntimeOrigin::signed(origin),
 					dest,
-					value,
+					native_value,
 					gas_limit,
 					storage_deposit_limit,
 					input.clone(),
 					debug,
 					collect_events,
 				);
+
 				let result = EthContractResult {
 					gas_required: result.gas_required,
 					storage_deposit: result.storage_deposit.charge_or_zero(),
@@ -1274,7 +1290,7 @@ where
 				// Get the dispatch info of the call.
 				let dispatch_call: <T as Config>::RuntimeCall = crate::Call::<T>::call {
 					dest,
-					value,
+					value: native_value,
 					gas_limit: result.gas_required,
 					storage_deposit_limit: result.storage_deposit,
 					data: input.clone(),
@@ -1300,7 +1316,7 @@ where
 				// Dry run the call.
 				let result = crate::Pallet::<T>::bare_instantiate(
 					T::RuntimeOrigin::signed(origin),
-					value,
+					native_value,
 					gas_limit,
 					storage_deposit_limit,
 					Code::Upload(code.to_vec()),
@@ -1320,7 +1336,7 @@ where
 				// Get the dispatch info of the call.
 				let dispatch_call: <T as Config>::RuntimeCall =
 					crate::Call::<T>::instantiate_with_code {
-						value,
+						value: native_value,
 						gas_limit: result.gas_required,
 						storage_deposit_limit: result.storage_deposit,
 						code: code.to_vec(),
@@ -1333,7 +1349,7 @@ where
 		};
 
 		let mut tx = TransactionLegacyUnsigned {
-			value: value.into().saturating_mul(T::NativeToEthRatio::get().into()),
+			value,
 			input: input.into(),
 			nonce: nonce.into(),
 			chain_id: Some(T::ChainId::get().into()),
@@ -1372,6 +1388,12 @@ where
 		result
 	}
 
+	/// Get the balance with EVM decimals of the given `address`.
+	pub fn evm_balance(address: &H160) -> U256 {
+		let account = T::AddressMapper::to_account_id(&address);
+		Self::convert_native_to_evm(T::Currency::reducible_balance(&account, Preserve, Polite))
+	}
+
 	/// A generalized version of [`Self::upload_code`].
 	///
 	/// It is identical to [`Self::upload_code`] and only differs in the information it returns.
@@ -1424,6 +1446,25 @@ where
 				.and_then(|r| r)
 		})
 	}
+
+	/// Convert a native balance to EVM balance.
+	fn convert_native_to_evm(value: BalanceOf<T>) -> U256 {
+		value.into().saturating_mul(T::NativeToEthRatio::get().into())
+	}
+
+	/// Convert an EVM balance to a native balance.
+	fn convert_evm_to_native(value: U256) -> Result<BalanceOf<T>, Error<T>> {
+		if value.is_zero() {
+			return Ok(Zero::zero())
+		}
+		let ratio = T::NativeToEthRatio::get().into();
+		let res = value.checked_div(ratio).expect("divisor is non-zero; qed");
+		if res.saturating_mul(ratio) == value {
+			res.try_into().map_err(|_| Error::<T>::BalanceConversionFailed)
+		} else {
+			Err(Error::<T>::DecimalPrecisionLoss)
+		}
+	}
 }
 
 impl<T: Config> Pallet<T> {
@@ -1451,8 +1492,8 @@ sp_api::decl_runtime_apis! {
 		BlockNumber: Codec,
 		EventRecord: Codec,
 	{
-		/// Returns the free balance of the given `[H160]` address.
-		fn balance(address: H160) -> Balance;
+		/// Returns the free balance of the given `[H160]` address, using EVM decimals.
+		fn balance(address: H160) -> U256;
 
 		/// Returns the nonce of the given `[H160]` address.
 		fn nonce(address: H160) -> Nonce;
@@ -1489,7 +1530,7 @@ sp_api::decl_runtime_apis! {
 		fn eth_transact(
 			origin: H160,
 			dest: Option<H160>,
-			value: Balance,
+			value: U256,
 			input: Vec<u8>,
 			gas_limit: Option<Weight>,
 			storage_deposit_limit: Option<Balance>,