{"id":15448696,"url":"https://github.com/openethereum/pwasm-tutorial","last_synced_at":"2025-10-11T12:31:49.671Z","repository":{"id":113253784,"uuid":"114657371","full_name":"openethereum/pwasm-tutorial","owner":"openethereum","description":"A step-by-step tutorial on how to write contracts in Wasm for Kovan","archived":true,"fork":false,"pushed_at":"2019-07-11T13:12:41.000Z","size":213,"stargazers_count":227,"open_issues_count":8,"forks_count":34,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-10-10T22:02:51.711Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/openethereum.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-12-18T15:32:19.000Z","updated_at":"2025-06-17T23:17:42.000Z","dependencies_parsed_at":null,"dependency_job_id":"553e9ee5-03ca-4426-bf61-e41f51dd7be8","html_url":"https://github.com/openethereum/pwasm-tutorial","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/openethereum/pwasm-tutorial","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openethereum%2Fpwasm-tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openethereum%2Fpwasm-tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openethereum%2Fpwasm-tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openethereum%2Fpwasm-tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/openethereum","download_url":"https://codeload.github.com/openethereum/pwasm-tutorial/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openethereum%2Fpwasm-tutorial/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279007167,"owners_count":26084247,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-11T02:00:06.511Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-01T20:29:13.877Z","updated_at":"2025-10-11T12:31:49.665Z","avatar_url":"https://github.com/openethereum.png","language":"Rust","readme":"## Tutorial Prerequisites\nThere is a list of all tools and dependencies required for this tutorial.\n\n### Rust\n[rustup](https://github.com/rust-lang-nursery/rustup.rs#installation) is the easiest way to install Rust toolchains. Rust nightly toolchain is required since our contracts require some unstable features:\n\n```bash\nrustup install nightly-2018-11-12\n```\n\nAlso, we need to install `wasm32-unknown-unknown` to compile contracts to Wasm:\n```bash\nrustup target add wasm32-unknown-unknown\n```\n\n### Parity wasm-build\n[wasm-build](https://github.com/paritytech/wasm-utils#build-tools-for-cargo) takes the raw `.wasm` file produced by Rust compiler and packs it to the form of valid contract.\n```\ncargo install pwasm-utils-cli --bin wasm-build\n```\n\n### Parity\nFollow the [parity setup guide](https://wiki.parity.io/Setup). You'll need Parity version **1.9.5** or later.\n\n### Web3.js\nWe'll be using `Web3.js` to connect to the Parity node. Change dir to the root `pwasm-tutorial` and run [yarn](https://yarnpkg.com) or [npm](https://nodejs.org) to install `Web3.js`:\n```\nyarn install\n```\n\n### Tutorial source code\nWe provide a full source code for each step in this tutorial under `step-*` directories.\n\n## General structure\nSource code: https://github.com/paritytech/pwasm-tutorial/tree/master/step-0\n\n```rust\n// Contract doesn't use Rust's standard library\n#![no_std]\n\n// `pwasm-ethereum` implements bindings to the runtime\nextern crate pwasm_ethereum;\n\n/// Will be described in the next step\n#[no_mangle]\npub fn deploy() {\n}\n\n/// The call function is the main function of the *deployed* contract\n#[no_mangle]\npub fn call() {\n    // Send a result pointer to the runtime\n    pwasm_ethereum::ret(\u0026b\"result\"[..]);\n}\n```\n### pwasm-ethereum\n[pwasm-ethereum](https://github.com/NikVolf/pwasm-ethereum) is a collection of bindings to interact with ethereum-like network.\n\n## Building\nTo make sure that everything is set up go to the `step-0` directory and run `./build.sh`\n\nAs a result the `pwasm_tutorial_contract.wasm` should be created in the `target` directory.\n\nTake a look on the contents of the `./build.sh` executable:\n\n```\n#!/bin/bash\n\ncargo build --release --target wasm32-unknown-unknown\nwasm-build --target=wasm32-unknown-unknown ./target pwasm_tutorial_contract\n```\n\nFirst, we run `cargo build --release --target wasm32-unknown-unknown` which yields a \"raw\" Wasm binary and put it into the \"target\" directory: `target/wasm32-unknown-unknown/release/pwasm_tutorial_contract.wasm`. Then we run the `wasm-build` tool. It takes `pwasm_tutorial_contract.wasm` raw file generated by `cargo build`, trims, optimises it and produces the so-called contract \"constructor\". It packs the actual contract code into that constructor. So on deploy, executor will put the raw contract code into the blockchain as a result of the successful transaction.\n\nFor your convenience, every step in our tutorial features a `build.sh` shell script, which incorporates the proper `wasm-build` call (unfortunately, cargo's build pipeline is not yet extensible enough to feature such steps automatically). Alternatively, one can trivially call the same wasm packing manually after every build.\n\n## The constructor\nSource code: https://github.com/paritytech/pwasm-tutorial/tree/master/step-1\n\nWhen deploying a contract we often want to set its initial storage values (e.g. `totalSupply` if it's a token contact). To address this problem we are exporting another function \"deploy\" which executes only once on contract deployment.\n\n```rust\n// This contract will return the address from which it was deployed\n#![no_std]\n\nextern crate pwasm_ethereum;\nextern crate parity_hash;\n\nuse parity_hash::H256;\n\n// The \"deploy\" will be executed only once on deployment but will not be stored on the blockchain\n#[no_mangle]\npub fn deploy() {\n    // Lets set the sender address to the contract storage at address \"0\"\n    pwasm_ethereum::write(\u0026H256::zero().into(), \u0026H256::from(pwasm_ethereum::sender()).into());\n    // Note we shouldn't write any result into the call descriptor in deploy.\n}\n\n// The following code will be stored on the blockchain.\n#[no_mangle]\npub fn call() {\n    // Will read the address of the deployer which we wrote to the storage on the deploy stage\n    let owner = pwasm_ethereum::read(\u0026H256::zero().into());\n    // Send a result pointer to the runtime\n    pwasm_ethereum::ret(owner.as_ref());\n}\n```\n\n## Contract ABI declaration\nSource code: https://github.com/paritytech/pwasm-tutorial/tree/master/step-2\n\nLet's implement a simple [ERC-20](https://en.wikipedia.org/wiki/ERC20) token contract.\n\n```rust\n// ...\n\npub mod token {\n    use pwasm_ethereum;\n    use pwasm_abi::types::*;\n\n    // eth_abi is a procedural macros https://doc.rust-lang.org/book/first-edition/procedural-macros.html\n    use pwasm_abi_derive::eth_abi;\n\n    lazy_static! {\n        static ref TOTAL_SUPPLY_KEY: H256 =\n            H256::from([2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);\n    }\n\n    #[eth_abi(TokenEndpoint)]\n    pub trait TokenInterface {\n\t/// The constructor\n        fn constructor(\u0026mut self, _total_supply: U256);\n        /// Total amount of tokens\n        fn totalSupply(\u0026mut self) -\u003e U256;\n    }\n\n    pub struct TokenContract;\n\n    impl TokenInterface for TokenContract {\n        fn constructor(\u0026mut self, total_supply: U256) {\n            // Set up the total supply for the token\n            pwasm_ethereum::write(\u0026TOTAL_SUPPLY_KEY, \u0026total_supply.into());\n        }\n\n        fn totalSupply(\u0026mut self) -\u003e U256 {\n            pwasm_ethereum::read(\u0026TOTAL_SUPPLY_KEY).into()\n        }\n    }\n}\n// Declares the dispatch and dispatch_ctor methods\nuse pwasm_abi::eth::EndpointInterface;\n\n#[no_mangle]\npub fn call() {\n    let mut endpoint = token::TokenEndpoint::new(token::TokenContract{});\n    // Read http://solidity.readthedocs.io/en/develop/abi-spec.html#formal-specification-of-the-encoding for details\n    pwasm_ethereum::ret(\u0026endpoint.dispatch(\u0026pwasm_ethereum::input()));\n}\n\n#[no_mangle]\npub fn deploy() {\n    let mut endpoint = token::TokenEndpoint::new(token::TokenContract{});\n    //\n    endpoint.dispatch_ctor(\u0026pwasm_ethereum::input());\n}\n\n```\n`token::TokenInterface` is an interface definition of the contract.\n`pwasm_abi_derive::eth_abi` is a [procedural macros](https://doc.rust-lang.org/book/first-edition/procedural-macros.html) uses a trait `token::TokenInterface` to generate decoder (`TokenEndpoint`) for payload in Solidity ABI format. `TokenEndpoint` implements an `EndpointInterface` trait:\n\n```rust\n/// Endpoint interface for contracts\npub trait EndpointInterface {\n\t/// Dispatch payload for regular method\n\tfn dispatch(\u0026mut self, payload: \u0026[u8]) -\u003e Vec\u003cu8\u003e;\n\n\t/// Dispatch constructor payload\n\tfn dispatch_ctor(\u0026mut self, payload: \u0026[u8]);\n}\n```\n\nThe `dispatch` expects `payload` and returns a result in the format defined in [Solidity ABI spec](http://solidity.readthedocs.io/en/develop/abi-spec.html#formal-specification-of-the-encoding). It maps payload to the corresponding method of the `token::TokenInterface` implementation. The `dispatch_ctor` maps payload only to the `TokenInterface::constructor` and returns no result.\n\nA complete implementation of ERC20 can be found here https://github.com/paritytech/pwasm-token-example.\n\n### pwasm-std\n[pwasm-std](https://paritytech.github.io/pwasm-std/pwasm_std/) is a lightweight standard library. It implements common data structures, conversion utils and provides bindings to the runtime.\n\n## Make calls to other contracts\nSource code: https://github.com/paritytech/pwasm-tutorial/tree/master/step-3\n\nIn order to make calls to our `TokenInterface` we need to generate the payload `TokenEndpoint::dispatch()` expects. So `pwasm_abi_derive::eth_abi` can generate an implementation of `TokenInterface` which will prepare payload for each method.\n\n```rust\n#[eth_abi(TokenEndpoint, TokenClient)]\npub trait TokenInterface {\n    /// The constructor\n    fn constructor(\u0026mut self, _total_supply: U256);\n    /// Total amount of tokens\n    #[constant] // #[constant] hint affect the resulting JSON abi. It sets \"constant\": true prore\n    fn totalSupply(\u0026mut self) -\u003e U256;\n}\n```\n\nWe've added a second argument `TokenClient` to the `eth_abi` macro as a second argument (it is optional) -- this way we ask to generate a _client_ implementation for `TokenInterface` trait and name it as `TokenClient`.\n\nAs mentioned [above](https://github.com/paritytech/pwasm-tutorial/blob/master/README.md#contract-abi-declaration), a first argument to the `eth_abi` macro requests the name for to be generated Endpoint implementation, which turns Ethereum ABI-encoded payloads into calls to the corresponding `TokenContract` methods with deserialized params.\n\n*Client* (`TokenClient`), created via the second argument, is doing the opposite to *endpoint*, providing an implementation which generates Ethereum ABI-compatible calls (consumable by `TokenEndpoint`) for every `TokenInterface` call.\n\nLet's suppose we've deployed a token contract on `0x7BA4324585CB5597adC283024819254345CD7C62` address. That's how we can make calls to it.\n\n```rust\nextern pwasm_ethereum;\nextern pwasm_std;\n\nuse token::TokenClient;\nuse pwasm_std::hash::Address;\n\nlet token = TokenClient::new(Address::from(\"0x7BA4324585CB5597adC283024819254345CD7C62\"));\nlet tokenSupply = token.totalSupply();\n```\n\n`token.totalSupply()` will execute `pwasm_ethereum::call(Address::from(\"0x7BA4324585CB5597adC283024819254345CD7C62\"), payload)` with `address` and `payload` generated according to `totalSupply()` signature. Optionally it's possible to set a `value` (in Wei) to transfer with the call and set a `gas` limit.\n\n```rust\nlet token = TokenClient::new(Address::from(\"0x7BA4324585CB5597adC283024819254345CD7C62\"))\n\t.value(10000000.into()) // send a value with the call\n\t.gas(21000); // set a gas limit\nlet tokenSupply = token.totalSupply();\n```\n\nIf you move to `step-3` directory and run `cargo build --release --target wasm32-unknown-unknown` you will find a `TokenInterface.json` in the `target/json` generated from `TokenInterface` trait with the following content:\n\n```json\n[\n  {\n    \"type\": \"function\",\n    \"name\": \"totalSupply\",\n    \"inputs\": [],\n    \"outputs\": [\n      {\n        \"name\": \"returnValue\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"constant\": true\n  },\n  {\n    \"type\": \"constructor\",\n    \"inputs\": [\n      {\n        \"name\": \"_total_supply\",\n        \"type\": \"uint256\"\n      }\n    ]\n  }\n]\n```\n\nJSON above is an ABI definition which can be used along with Web.js to run transactions and calls to contract:\n\n```javascript\nvar Web3 = require(\"web3\");\nvar fs = require(\"fs\");\nvar web3 = new Web3(new Web3.providers.HttpProvider(\"http://localhost:8545\"));\nvar abi = JSON.parse(fs.readFileSync(\"./target/TokenInterface.json\"));\nvar TokenContract = new web3.eth.Contract(abi, \"0x7BA4324585CB5597adC283024819254345CD7C62\", { from: web3.eth.defaultAccount });\nvar totalSupply = TokenContract.methods.totalSupply().call().then(console.log);\n```\n\n### Events\nSource code: https://github.com/paritytech/pwasm-tutorial/tree/master/step-4\n\nEvents allow the convenient usage of the EVM logging facilities, which in turn can be used to “call” JavaScript callbacks in the user interface of a dapp, which listen for these events.\n\nLet's implement the `transfer` method for our ERC-20 contract. `step-4` directory contains the complete implementation.\n\n```rust\npub mod token {\n\n    use pwasm_ethereum;\n    use pwasm_std::types::*;\n\n    #[eth_abi(TokenEndpoint, TokenClient)]\n    pub trait TokenInterface {\n        /// The constructor\n        fn constructor(\u0026mut self, _total_supply: U256);\n        /// Total amount of tokens\n        #[constant]\n        fn totalSupply(\u0026mut self) -\u003e U256;\n        /// What is the balance of a particular account?\n        #[constant]\n        fn balanceOf(\u0026mut self, _owner: Address) -\u003e U256;\n        /// Transfer the balance from owner's account to another account\n        fn transfer(\u0026mut self, _to: Address, _amount: U256) -\u003e bool;\n        /// Event declaration\n        #[event]\n        fn Transfer(\u0026mut self, indexed_from: Address, indexed_to: Address, _value: U256);\n    }\n\n    pub struct TokenContract;\n\n    impl TokenInterface for TokenContract {\n        fn constructor(\u0026mut self, total_supply: U256) {\n            // ...\n        }\n\n        fn totalSupply(\u0026mut self) -\u003e U256 {\n            // ...\n        }\n\n        fn balanceOf(\u0026mut self, owner: Address) -\u003e U256 {\n            read_balance_of(\u0026owner)\n        }\n\n        fn transfer(\u0026mut self, to: Address, amount: U256) -\u003e bool {\n            let sender = pwasm_ethereum::sender();\n            let senderBalance = read_balance_of(\u0026sender);\n            let recipientBalance = read_balance_of(\u0026to);\n            if amount == 0.into() || senderBalance \u003c amount || to == sender {\n                false\n            } else {\n                let new_sender_balance = senderBalance - amount;\n                let new_recipient_balance = recipientBalance + amount;\n                pwasm_ethereum::write(\u0026balance_key(\u0026sender), \u0026new_sender_balance.into());\n                pwasm_ethereum::write(\u0026balance_key(\u0026to), \u0026new_recipient_balance.into());\n                self.Transfer(sender, to, amount);\n                true\n            }\n        }\n    }\n\n    // Reads balance by address\n    fn read_balance_of(owner: \u0026Address) -\u003e U256 {\n        pwasm_ethereum::read(\u0026balance_key(owner)).into()\n    }\n\n    // Generates a balance key for some address.\n    // Used to map balances with their owners.\n    fn balance_key(address: \u0026Address) -\u003e H256 {\n        let mut key = H256::from(*address);\n        key.as_bytes_mut()[0] = 1; // just a naive \"namespace\";\n        key\n    }\n}\n```\n\nEvents are declared as part of a contract trait definition. Arguments which start with the \"indexed_\" prefix are considered as \"topics\", other arguments are data associated with an event.\n\n```rust\n#[eth_abi(TokenEndpoint, TokenClient)]\npub trait TokenInterface {\n    fn transfer(\u0026mut self, _to: Address, _amount: U256) -\u003e bool;\n    #[event]\n    fn Transfer(\u0026mut self, indexed_from: Address, indexed_to: Address, _value: U256);\n}\n\nfn transfer(\u0026mut self, to: Address, amount: U256) -\u003e bool {\n    let sender = pwasm_ethereum::sender();\n    let senderBalance = read_balance_of(\u0026sender);\n    let recipientBalance = read_balance_of(\u0026to);\n    if amount == 0.into() || senderBalance \u003c amount || to == sender {\n        false\n    } else {\n        let new_sender_balance = senderBalance - amount;\n        let new_recipient_balance = recipientBalance + amount;\n        pwasm_ethereum::write(\u0026balance_key(\u0026sender), \u0026new_sender_balance.into());\n        pwasm_ethereum::write(\u0026balance_key(\u0026to), \u0026new_recipient_balance.into());\n        self.Transfer(sender, to, amount);\n        true\n    }\n}\n```\n\nTopics are useful to filter events produced by contract. In following example we use Web3.js to subscribe to the `Transfer` events of deployed `TokenContract`.\n```javascript\nvar Web3 = require(\"web3\");\nvar web3 = new Web3(new Web3.providers.HttpProvider(\"http://localhost:8545\"));\nvar abi = JSON.parse(fs.readFileSync(\"./target/TokenInterface.json\"));\nvar TokenContract = new web3.eth.Contract(abi, \"0x7BA4324585CB5597adC283024819254345CD7C62\", { from: web3.eth.defaultAccount });\n\n// Subscribe to the Transfer event\nTokenContract.events.Transfer({\n    from: \"0x7BA4324585CB5597adC283024819254345CD7C62\" // Filter transactions by sender\n}, function (err, event) {\n    console.log(event);\n});\n```\n\n## Run node and deploy contract\nNow it's time to deploy our Wasm contract on the blockchain. We can either test in own local development chain or publish it on the public Kovan network.\n\n### Option 1: Setup and run development node\nParity **1.9.5** includes support for running Wasm contracts.\nSee [instructions](dev-node-setup.md) on how to setup a Wasm-enabled dev node.\n\n### Option 2: Run Kovan node\nKovan network supports Wasm contracts. This will run Parity node on Kovan:\n```bash\nparity --chain kovan\n```\nWhen it syncs up follow https://github.com/kovan-testnet/faucet to set up an account with some Kovan ETH to be able to pay gas for transactions.\n\n### Deploy\nLet Parity run in a separate terminal window.\n\nNow cd to `step-5` and build the contract:\n```bash\n./build.sh\n```\nIt should produce 2 files we need:\n- a compiled Wasm binary `./target/pwasm_tutorial_contract.wasm`\n- an ABI file: `./target/json/TokenInterface.json`\n\nAt this point we can use Web.js to connect to the Parity node and deploy Wasm `pwasm_tutorial_contract.wasm`. Run the following code in `node` console:\n\n```javascript\nvar Web3 = require(\"web3\");\nvar fs = require(\"fs\");\n// Connect to our local node\nvar web3 = new Web3(new Web3.providers.HttpProvider(\"http://localhost:8545\"));\n// NOTE: if you run Kovan node there should be an address you've got in the \"Option 2: Run Kovan node\" step\nweb3.eth.defaultAccount = \"0x004ec07d2329997267ec62b4166639513386f32e\";\n// read JSON ABI\nvar abi = JSON.parse(fs.readFileSync(\"./target/json/TokenInterface.json\"));\n// convert Wasm binary to hex format\nvar codeHex = '0x' + fs.readFileSync(\"./target/pwasm_tutorial_contract.wasm\").toString('hex');\n\nvar TokenContract = new web3.eth.Contract(abi, { data: codeHex, from: web3.eth.defaultAccount });\n\nvar TokenDeployTransaction = TokenContract.deploy({data: codeHex, arguments: [10000000]});\n\n// Will create TokenContract with `totalSupply` = 10000000 and print a result\nweb3.eth.personal.unlockAccount(web3.eth.defaultAccount, \"user\").then(() =\u003e TokenDeployTransaction.estimateGas()).then(gas =\u003e TokenDeployTransaction.send({gasLimit: gas, from: web3.eth.defaultAccount})).then(contract =\u003e { console.log(\"Address of new contract: \" + contract.options.address); TokenContract = contract; }).catch(err =\u003e console.log(err));\n```\nNow we're able transfer some tokens:\n```javascript\nweb3.eth.personal.unlockAccount(web3.eth.defaultAccount, \"user\").then(() =\u003e TokenContract.methods.transfer(\"0x7BA4324585CB5597adC283024819254345CD7C62\", 200).send()).then(console.log).catch(console.log);\n```\n\nAnd check balances:\n```javascript\n// Check balance of recipient. Should print 200\nTokenContract.methods.balanceOf(\"0x7BA4324585CB5597adC283024819254345CD7C62\").call().then(console.log).catch(console.log);\n\n// Check balance of sender (owner of the contract). Should print 10000000 - 200 = 9999800\nTokenContract.methods.balanceOf(web3.eth.defaultAccount).call().then(console.log).catch(console.log);\n```\n\n## Testing\n[pwasm-test](https://github.com/paritytech/pwasm-test) makes it easy to test a contract's logic. It allows to emulate the blockchain state and mock any [pwasm-ethereum](#pwasm-ethereum) call.\n\nBy default our contracts built with `#![no_std]`, but `rust test` needs the Rust stdlib for threading and I/O. Thus, in order to run tests we've added a following feature gate in [Cargo.toml](https://github.com/paritytech/pwasm-tutorial/tree/master/step-5):\n\n```\n[features]\nstd = [\"pwasm-std/std\", \"pwasm-ethereum/std\"]\n```\nNow you can `cd step-5` and `cargo test --features std` should pass.\n\nTake a look https://github.com/paritytech/pwasm-tutorial/blob/master/step-5/src/lib.rs#L116-L161 to see an example how to test a `transfer` method of our token contract.\n\n```rust\n#[cfg(test)]\n#[allow(non_snake_case)]\nmod tests {\n    extern crate pwasm_test;\n    extern crate std;\n    use super::*;\n    use self::pwasm_test::{ext_reset, ext_get};\n    use parity_hash::Address;\n    use token::TokenInterface;\n\n    #[test]\n    fn should_succeed_transfering_1000_from_owner_to_another_address() {\n        let mut contract = token::TokenContract{};\n        let owner_address = Address::from(\"0xea674fdde714fd979de3edf0f56aa9716b898ec8\");\n        let sam_address = Address::from(\"0xdb6fd484cfa46eeeb73c71edee823e4812f9e2e1\");\n        // Here we're creating an External context using ExternalBuilder and set the `sender` to the `owner_address`\n        // so `pwasm_ethereum::sender()` in TokenContract::constructor() will return that `owner_address`\n        ext_reset(|e| e.sender(owner_address.clone()));\n        let total_supply = 10000.into();\n        contract.constructor(total_supply);\n        assert_eq!(contract.balanceOf(owner_address), total_supply);\n        assert_eq!(contract.transfer(sam_address, 1000.into()), true);\n        assert_eq!(contract.balanceOf(owner_address), 9000.into());\n        assert_eq!(contract.balanceOf(sam_address), 1000.into());\n        // 1 log entry should be created\n        assert_eq!(ext_get().logs().len(), 1);\n    }\n}\n```\n\n[Here](https://github.com/paritytech/pwasm-test/tree/master/tests) you can find more examples on how to:\n- [mock calls](https://github.com/paritytech/pwasm-test/blob/master/tests/calls.rs) to other contracts\n- [read event logs created by contract](https://github.com/paritytech/pwasm-test/blob/master/tests/log.rs)\n- [init contract with storage](https://github.com/paritytech/pwasm-test/blob/master/tests/storage_read.rs).\n\nMore testing examples:\nhttps://github.com/paritytech/pwasm-token-example/blob/master/contract/src/lib.rs#L194\n\nIn order to test the interaction between contracts, we're able to mock callee contract client. See comprehensive here:\nhttps://github.com/paritytech/pwasm-repo-contract/blob/master/contract/src/lib.rs#L453\n","funding_links":[],"categories":["Tutorial Repositories"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenethereum%2Fpwasm-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenethereum%2Fpwasm-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenethereum%2Fpwasm-tutorial/lists"}