{"id":13652748,"url":"https://github.com/nervosnetwork/polyjuice","last_synced_at":"2025-04-23T03:31:17.125Z","repository":{"id":55161502,"uuid":"263503917","full_name":"nervosnetwork/polyjuice","owner":"nervosnetwork","description":"An Ethereum on CKB solution","archived":true,"fork":false,"pushed_at":"2021-01-07T07:20:38.000Z","size":516,"stargazers_count":19,"open_issues_count":1,"forks_count":4,"subscribers_count":3,"default_branch":"develop","last_synced_at":"2024-11-10T03:35:43.146Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nervosnetwork.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-05-13T02:22:09.000Z","updated_at":"2023-01-28T11:12:06.000Z","dependencies_parsed_at":"2022-08-14T14:02:42.458Z","dependency_job_id":null,"html_url":"https://github.com/nervosnetwork/polyjuice","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nervosnetwork%2Fpolyjuice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nervosnetwork%2Fpolyjuice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nervosnetwork%2Fpolyjuice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nervosnetwork%2Fpolyjuice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nervosnetwork","download_url":"https://codeload.github.com/nervosnetwork/polyjuice/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250365517,"owners_count":21418698,"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","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-08-02T02:01:02.267Z","updated_at":"2025-04-23T03:31:16.390Z","avatar_url":"https://github.com/nervosnetwork.png","language":"Rust","funding_links":[],"categories":["Tools"],"sub_categories":["Other"],"readme":"# Polyjuice\n\n\u003e This is the deprecated standalone polyjuice implementation. See https://github.com/nervosnetwork/godwoken-polyjuice for godwoken polyjuice.\n\nNervos CKB is built on the cell model, which is a generalized version of the UTXO model. There seems to be a belief in the blockchain world that UTXO model is hard to program on, while the account model is easier for developers. Although cell model is a descendant of UTXO model, it is perfectly [possible](https://xuejie.space/2020_03_20_what_do_we_mean_when_we_say_account_model/) to build account model on top of cell model. The secret here also lies in abstraction. While at the lower level UTXO-style design can help achieve parallelism, at the higher level an abstraction layer can expose exactly an account model to the everyday developers.\n\nThat is also just our claim, as engineers we all know the famous quote \"Talk is cheap. Show me the code.\" Following this principle, we designed and built polyjuice, which is an Ethereum compatible layer on top of Nervos CKB. Ethereum, up to this day, is probably the most used and flexible account model based blockchain. By polyjuice we want to showcase that it is perfectly possible to use account model on Nervos CKB. The flexibility here actually enables countless opportunities.\n\n# Features\n- [x] Contract creation\n- [x] Contract destruction\n- [x] Contract call contract\n- [x] Contract logs\n- [x] Read block information from contract\n- [x] Value transfer\n\nPolyjuice use [evmone](https://github.com/ethereum/evmone) as the EVM implementation in both `generator` and `validator`, all opcodes (if none is missing) are supported.\n\n\n# A short tutorial\n\n**NOTE** : The tutorial currently only tested on Ubuntu 18.04.\n\nHere we provide a short tutorial performing the following operations on a polyjuice on CKB setup:\n\n* Simple contract creation\n* Calling contract\n* Reading storage data from a contract\n\nThroughout the tutorial, we will work with the following 2 accounts:\n\n* Account A\n  - private key: `d00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc`\n  - CKB address: `ckt1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts8vyj37`\n  - Ethereum address: `0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7`\n* Account B\n  - private key: `3066aa42bfa95c6d033edfad9d1efb871991fd26f56270fedc171559823bee77`\n  - CKB address: `ckt1qyqgjagv5f8xq9syxd38v2ga3dczszqy67psu2y8r4`\n  - Ethereum address: `0x89750ca24e601604336276291d8b70280804d783`\n\nNote that Ethereum address is also CKB secp256k1 sighash lock args.\n\n## Setting up CKB\n\nYou need to download latest CKB from github [release page](https://github.com/nervosnetwork/ckb/releases). For convenience, we will launch a dev chain locally and work from there.\n\nTo initialize the dev chain, you can just use the init command:\n\n```bash\n$ ckb init --chain dev --ba-arg 0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7\n```\n\nNow we can launch CKB and the miner:\n\n``` bash\n$ ckb run\n\n# in a different terminal\n$ ckb miner\n```\n\n## Install ckb-cli / jq\n\nSince we need to sign secp256k1 sighash locked inputs in polyjuice generated transaction, we need a little help from `ckb-cli`. You need to build a special version of [ckb-cli](https://github.com/TheWaWaR/ckb-cli/tree/skip-check-to-address) (for support `type-id` and skip check to-address argument), and put in your `$PATH`, so polyjuice can find it.\n\n``` bash\n$ git clone -b skip-check-to-address https://github.com/TheWaWaR/ckb-cli\n$ cd ckb-cli\n$ cargo install --locked -f --path .\n```\n\nSome actions depend on `jq` to show/edit json information. You may install [jq](https://stedolan.github.io/jq/download/) by:\n\n```bash\n$ sudo apt install jq -y\n```\n\n## Setting up polyjuice\n\nNow we are ready to setup polyjuice:\n\n```bash\n$ git clone https://github.com/nervosnetwork/polyjuice\n$ cd polyjuice\n$ git submodule update --init --recursive --progress\n$ cargo build --release\n```\n\nBuild c contracts:\n\n``` bash\n$ cd c\n$ make all-via-docker\n$ cd ..\n```\n\nIt will build a `validator` for running in polyjuice type script, and a `generator` for generating CKB transaction.\n\nBefore deploy contracts we better save privkey to a file for convenience (NOTE: this is insecure):\n\n```bash\necho \"d00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc\" \u003e privkey-0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7\n```\n\nThen we use ckb-cli to deploy `validator` to dev chain:\n\n```bash\n$ ckb-cli wallet transfer \\\n        --privkey-path privkey-0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7 \\\n        --to-address ckt1qyqgjagv5f8xq9syxd38v2ga3dczszqy67psu2y8r4 \\\n        --tx-fee 0.01 \\\n        --capacity 300000 \\\n        --to-data-path ./c/build/validator\n\n# The transaction where validator contract's code located\n0x1111000000000000000000000000000000000000000000000000000000000000\n```\n\nSince lock script is required for every cell and we want anyone can use the contract, here we deploy an always success contract for polyjuice cell's lock script:\n\n```bash\n$ ckb-cli wallet transfer \\\n        --privkey-path privkey-0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7 \\\n        --to-address ckt1qyqgjagv5f8xq9syxd38v2ga3dczszqy67psu2y8r4 \\\n        --tx-fee 0.001 \\\n        --capacity 600 \\\n        --to-data 0x7f454c460201010000000000000000000200f3000100000078000100000000004000000000000000980000000000000005000000400038000100400003000200010000000500000000000000000000000000010000000000000001000000000082000000000000008200000000000000001000000000000001459308d00573000000002e7368737472746162002e74657874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000010000000600000000000000780001000000000078000000000000000a0000000000000000000000000000000200000000000000000000000000000001000000030000000000000000000000000000000000000082000000000000001100000000000000000000000000000001000000000000000000000000000000\n\n# The transaction where always success contract's code located\n0x2222000000000000000000000000000000000000000000000000000000000000\n```\n\nSince we need an EoA(Externally Owned Account) account to send the transaction, we deploy a [anyone-can-pay](https://github.com/thewawar/ckb-anyone-can-pay) contract for EoA cell's lock script, for convenience we can use a pre-compiled binary in tests directory:\n\n```bash\n$ ckb-cli wallet transfer \\\n        --privkey-path privkey-0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7 \\\n        --to-address ckt1qyqdfjzl8ju2vfwjtl4mttx6me09hayzfldq8m3a0y \\\n        --tx-fee 0.01 \\\n        --capacity 60000 \\\n        --to-data-path ./tests/anyone_can_pay\n\n# The transaction hash\n0x3333000000000000000000000000000000000000000000000000000000000000\n```\n\nRunning polyjuice require a config file to tell polyjuice the `validator`/`always_success`/`anyone-can-pay` contract's out point and code hash. We use `ckb-cli` to calculate the code hash:\n\n```bash\n# validator's code hash\n$ ckb-cli util blake2b --binary-path ./c/build/validator\n0xaaaa000000000000000000000000000000000000000000000000000000000000\n\n# always_success's code hash\n$ ckb-cli util blake2b --binary-hex 0x7f454c460201010000000000000000000200f3000100000078000100000000004000000000000000980000000000000005000000400038000100400003000200010000000500000000000000000000000000010000000000000001000000000082000000000000008200000000000000001000000000000001459308d00573000000002e7368737472746162002e74657874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000010000000600000000000000780001000000000078000000000000000a0000000000000000000000000000000200000000000000000000000000000001000000030000000000000000000000000000000000000082000000000000001100000000000000000000000000000001000000000000000000000000000000\n0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5\n\n# anyone-can-pay's code hash\n$ ckb-cli util blake2b --binary-path ./tests/anyone_can_pay\n0xbbbb000000000000000000000000000000000000000000000000000000000000\n```\n\nThen generate the config file:\n\n``` bash\n$ VALIDATOR_TX_HASH=0x1111000000000000000000000000000000000000000000000000000000000000\n$ VALIDATOR_CODE_HASH=0xaaaa000000000000000000000000000000000000000000000000000000000000\n$ ALWAYS_SUCCESS_TX_HASH=0x2222000000000000000000000000000000000000000000000000000000000000\n$ ANYONE_CAN_PAY_TX_HASH=0x3333000000000000000000000000000000000000000000000000000000000000\n$ ANYONE_CAN_PAY_CODE_HASH=0xbbbb000000000000000000000000000000000000000000000000000000000000\n\n$ cat \u003e run_config.json \u003c\u003c _RUN_CONFIG_\n{\n    \"type_dep\": {\n        \"out_point\": {\n            \"tx_hash\": \"${VALIDATOR_TX_HASH}\",\n            \"index\": \"0x0\"\n        },\n        \"dep_type\": \"code\"\n    },\n    \"type_script\": {\n        \"code_hash\": \"${VALIDATOR_CODE_HASH}\",\n        \"hash_type\": \"data\",\n        \"args\": \"0x\"\n    },\n    \"lock_dep\": {\n        \"out_point\": {\n            \"tx_hash\": \"${ALWAYS_SUCCESS_TX_HASH}\",\n            \"index\": \"0x0\"\n        },\n        \"dep_type\": \"code\"\n    },\n    \"lock_script\": {\n        \"code_hash\": \"0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5\",\n        \"hash_type\": \"data\",\n        \"args\": \"0x\"\n    },\n    \"eoa_lock_dep\": {\n        \"out_point\": {\n            \"tx_hash\": \"${ANYONE_CAN_PAY_TX_HASH}\",\n            \"index\": \"0x0\"\n        },\n        \"dep_type\": \"code\"\n    },\n    \"eoa_lock_script\": {\n        \"code_hash\": \"${ANYONE_CAN_PAY_CODE_HASH}\",\n        \"hash_type\": \"data\",\n        \"args\": \"0x\"\n    }\n}\n_RUN_CONFIG_\n```\n\nThen start polyjuice:\n\n```bash\nRUST_LOG=polyjuice=debug ./target/release/polyjuice run \\\n  --generator ./c/build/generator \\\n  --config ./run_config.json\n```\n\n## Interacting though RPC API\n\nWe will use curl to interact with polyjuice. Default RPC server listen address is `localhost:8214`.\n\n### Create EoA account\nFisrt we need an EoA account to send transaction:\n```bash\n$ ./target/release/polyjuice new-eoa-account -k privkey-0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7 --balance 10000.0\n\n[lock-arg]: 0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7\n[Command]: ckb-cli wallet transfer --privkey-path privkey-0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7 --to-address ckt1q293q9zd4ggsz5h83hgq9dz0g2fr3ja7uhnzq53qtlwx587zc4az4jpj324umxu73ej0h3txcsu9cw77kgvaway9qy9 --capacity 10126.0 --tx-fee 0.001 --type-id --skip-check-to-address\ntx-hash: 0x082a2c796a11b476be1ba8bbb8fab17fca7a1cd2167d58b5f21c62c52cabd4a9, output-index: 0\n[type_args]: a1b4eb8bf37c6894c11029ae7f3d542aea3bc0ddca1ce6a3580e07b536dc9cad\n[lock_args]: c8328aabcd9b9e8e64fbc566c4385c3bdeb219d7\n0xb16ac6204aef494c411ed9dcfd6909f8c2d74527\n```\n\nThe EoA account address is int the last line, which is `0xb16ac6204aef494c411ed9dcfd6909f8c2d74527`.\n\n### Create contract\nThen, let's create an [ERC20](https://etherscan.io/address/0xc3761eb917cd790b30dad99f6cc5b4ff93c4f9ea) contract:\n\n``` bash\necho '{\n    \"id\": 2,\n    \"jsonrpc\": \"2.0\",\n    \"method\": \"create\",\n    \"params\": [\"0xb16ac6204aef494c411ed9dcfd6909f8c2d74527\", \"0x\u003cthe ERC20 contract binary\u003e\", 0]\n}' \\\n| tr -d '\\n' \\\n| curl -s -H 'content-type: application/json' -d @- http://localhost:8214 \\\n| jq .result \u003e tx-receipt.json\n```\n\n```json\n{\n  \"entrance_contract\": \"0xfe68578683eb8deee4de1aca6c1ba8847c6d7691\",\n  \"created_addresses\": [\n    \"0xfe68578683eb8deee4de1aca6c1ba8847c6d7691\"\n  ],\n  \"destructed_addresses\": [],\n  \"logs\": [],\n  \"return_data\": \"0x6060604 ...... 806500029\",\n  \"tx_hash\": \"0x1111111111111111111111111111111111111111111111111111111111111111\",\n  \"tx\": {\n    \"cell_deps\": [\n      {\n        \"dep_type\": \"dep_group\",\n        \"out_point\": {\n          \"index\": \"0x0\",\n          \"tx_hash\": \"0xace5ea83c478bb866edf122ff862085789158f5cbff155b7bb5f13058555b708\"\n        }\n      },\n      {\n        \"dep_type\": \"code\",\n        \"out_point\": {\n          \"index\": \"0x0\",\n          \"tx_hash\": \"0xc6c27c3a371425011b3b20697e16342359746f9203cc29a0613dd6166c830a94\"\n        }\n      },\n      {\n        \"dep_type\": \"code\",\n        \"out_point\": {\n          \"index\": \"0x0\",\n          \"tx_hash\": \"0x301a76aeafdefe55d822ff7b25373591438cfd7055d21285e9389b76e3e92c4b\"\n        }\n      }\n    ],\n    \"header_deps\": [],\n    \"inputs\": [\n      {\n        \"previous_output\": {\n          \"index\": \"0x1\",\n          \"tx_hash\": \"0x6260fb79e81e8196233c32ee61392bf44332fd2883d889c81f22f03c0bbe7077\"\n        },\n        \"since\": \"0x0\"\n      }\n    ],\n    \"outputs\": [\n      {\n        \"capacity\": \"0x4a817c800\",\n        \"lock\": {\n          \"args\": \"0x\",\n          \"code_hash\": \"0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5\",\n          \"hash_type\": \"data\"\n        },\n        \"type\": {\n          \"args\": \"0x804988b0f61a786082cbed278d46a7e727954eca\",\n          \"code_hash\": \"0x76aa92a7045c92289a0c1dbd74585d5a2b7660aa796f25d92052a6b2f705f181\",\n          \"hash_type\": \"data\"\n        }\n      },\n      {\n        \"capacity\": \"0x1bc15206fd1b0a20\",\n        \"lock\": {\n          \"args\": \"0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7\",\n          \"code_hash\": \"0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8\",\n          \"hash_type\": \"type\"\n        },\n        \"type\": null\n      }\n    ],\n    \"outputs_data\": [\n      \"0x6cb306547af5f7e64e4f01d3624de0ad36e1625029f73f5d25529600e682388ae09ecb04e6e61109e7d392c7dc7fc110e8edf83ae661bb2074cef29a2dab3c77\",\n      \"0x\"\n    ],\n    \"version\": \"0x0\",\n    \"witnesses\": [\n      \"0x5a150000 ...... f94c48fe00000000\"\n    ]\n  }\n}\n```\n\nThe `entrance_contract` field which is `0xfe68578683eb8deee4de1aca6c1ba8847c6d7691` here contrains the ERC20 contract address we will create. The following actions will require this value as argument.\n\nThen we sign the transaction use polyjuice:\n\n``` bash\n$ ./target/release/polyjuice sign-tx \\\n  --privkey privkey-0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7 \\\n  --tx-receipt tx-receipt.json \\\n  --output signed-tx.json\n```\n\nThe last part is send the transaction to CKB use `ckb-cli`:\n\n```bash\n$ ckb-cli tx send --tx-file signed-tx.json --skip-check\n0xedcede37f52fc402e021e17bf1cc1eb1b64cd4611e82dbe071440857ed375055\n```\n\n### Query the information of contract\n\nThe contract metadata:\n\n```bash\necho '{\n    \"id\": 2,\n    \"jsonrpc\": \"2.0\",\n    \"method\": \"get_contracts\",\n    \"params\": [0, null]\n}' \\\n| tr -d '\\n' \\\n| curl -s -H 'content-type: application/json' -d @- http://localhost:8214 \\\n| jq\n```\n\n```json\n{\n  \"jsonrpc\": \"2.0\",\n  \"result\": [\n    {\n      \"address\": \"0xfe68578683eb8deee4de1aca6c1ba8847c6d7691\",\n      \"block_number\": 14,\n      \"code\": \"0x608060405260043 ... 9f64736f6c63430006060033\",\n      \"code_hash\": \"0x8e92ee4326804b8c5b911ad1cf31b1b44269a1f89453329b5162e5b04ac2eade\",\n      \"destructed\": false,\n      \"output_index\": 0,\n      \"tx_hash\": \"0xedcede37f52fc402e021e17bf1cc1eb1b64cd4611e82dbe071440857ed375055\"\n    }\n  ],\n  \"id\": 2\n}\n```\n\nThe contract change:\n\n```bash\necho '{\n    \"id\": 2,\n    \"jsonrpc\": \"2.0\",\n    \"method\": \"get_change\",\n    \"params\": [\"0xfe68578683eb8deee4de1aca6c1ba8847c6d7691\", null]\n}' \\\n| tr -d '\\n' \\\n| curl -s -H 'content-type: application/json' -d @- http://localhost:8214 \\\n| jq\n\n```\n\n```json\n{\n  \"jsonrpc\": \"2.0\",\n  \"result\": {\n    \"address\": \"0xfe68578683eb8deee4de1aca6c1ba8847c6d7691\",\n    \"is_create\": true,\n    \"logs\": [],\n    \"new_storage\": [\n      [\n        \"0xc883bc0d49add18e7c46e11b87235c3df58a5051abcb763ed021382a2fbd0a61\",\n        \"0x000000000000000000000000000000000000000204fce5e3e250261100000000\"\n      ],\n      [\n        \"0x0000000000000000000000000000000000000000000000000000000000000002\",\n        \"0x0000000000000000000000000000000000000000000000000000000000000012\"\n      ],\n      [\n        \"0x0000000000000000000000000000000000000000000000000000000000000003\",\n        \"0x000000000000000000000000000000000000000204fce5e3e250261100000000\"\n      ],\n      [\n        \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n        \"0x455243323000000000000000000000000000000000000000000000000000000a\"\n      ],\n      [\n        \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n        \"0x455243323000000000000000000000000000000000000000000000000000000a\"\n      ]\n    ],\n    \"number\": 14,\n    \"output_index\": 0,\n    \"tx_hash\": \"0xedcede37f52fc402e021e17bf1cc1eb1b64cd4611e82dbe071440857ed375055\",\n    \"tx_index\": 1,\n    \"tx_origin\": \"0xb16ac6204aef494c411ed9dcfd6909f8c2d74527\"\n  },\n  \"id\": 2\n}\n```\n\n\n### Call a contract\n\nBefore we make some changes to the contract let's query the balance of the ERC20 token issuer.\n\n```bash\necho '{\n    \"id\": 2,\n    \"jsonrpc\": \"2.0\",\n    \"method\": \"static_call\",\n    \"params\": [\n        \"0xb16ac6204aef494c411ed9dcfd6909f8c2d74527\",\n        \"0xfe68578683eb8deee4de1aca6c1ba8847c6d7691\",\n        \"0x70a08231000000000000000000000000b16ac6204aef494c411ed9dcfd6909f8c2d74527\"\n    ]\n}' \\\n| tr -d '\\n' \\\n| curl -s -H 'content-type: application/json' -d @- http://localhost:8214 \\\n| jq\n```\n\n```json\n{\n  \"jsonrpc\": \"2.0\",\n  \"result\": {\n    \"logs\": [],\n    \"return_data\": \"0x000000000000000000000000000000000000000204fce5e3e250261100000000\"\n  },\n  \"id\": 2\n}\n```\n\nWe need create another EoA account to transfer:\n\n```bash\n./target/release/polyjuice new-eoa-account -k privkey-0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7 --balance 10000.0\n[lock-arg]: 0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7\n[Command]: ckb-cli wallet transfer --privkey-path privkey-0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7 --to-address ckt1q293q9zd4ggsz5h83hgq9dz0g2fr3ja7uhnzq53qtlwx587zc4az4jpj324umxu73ej0h3txcsu9cw77kgvaway9qy9 --capacity 10126.0 --tx-fee 0.001 --type-id --skip-check-to-address\ntx-hash: 0xaaba80fc391641fc8590435335f2962d47b9caa181d408594ad61acfa668bad9, output-index: 0\n[type_args]: fc7514e6465efe5af146cb61aaf3d259896b05848ca0f40ebdf666053dc265c1\n[lock_args]: c8328aabcd9b9e8e64fbc566c4385c3bdeb219d7\n0x3d2a2c5afeb6ba873844581245325d7cbc890313\n```\n\nNow, let's transfer `555` ERC20 token from `0xb16ac6204aef494c411ed9dcfd6909f8c2d74527` to `0x3d2a2c5afeb6ba873844581245325d7cbc890313`. The args generated from ethabi will be `0xa9059cbb0000000000000000000000003d2a2c5afeb6ba873844581245325d7cbc890313000000000000000000000000000000000000000000000000000000000000022b`.\n\nFirst, we create a CKB transaction use polyjuice:\n\n```bash\necho '{\n    \"id\": 2,\n    \"jsonrpc\": \"2.0\",\n    \"method\": \"call\",\n    \"params\": [\n        \"0xb16ac6204aef494c411ed9dcfd6909f8c2d74527\",\n        \"0xfe68578683eb8deee4de1aca6c1ba8847c6d7691\",\n        \"0xa9059cbb0000000000000000000000003d2a2c5afeb6ba873844581245325d7cbc890313000000000000000000000000000000000000000000000000000000000000022b\",\n        0\n    ]\n}' \\\n| tr -d '\\n' \\\n| curl -s -H 'content-type: application/json' -d @- http://localhost:8214 \\\n| jq .result \u003e tx-receipt.json\n```\n\n```json\n{\n  \"entrance_contract\": \"0xfe68578683eb8deee4de1aca6c1ba8847c6d7691\",\n  \"created_addresses\": [],\n  \"destructed_addresses\": [],\n  \"logs\": [\n    {\n      \"address\": \"0xfe68578683eb8deee4de1aca6c1ba8847c6d7691\",\n      \"data\": \"0x000000000000000000000000000000000000000000000000000000000000022b\",\n      \"topics\": [\n        \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n        \"0x000000000000000000000000b16ac6204aef494c411ed9dcfd6909f8c2d74527\",\n        \"0x0000000000000000000000003d2a2c5afeb6ba873844581245325d7cbc890313\"\n      ]\n    }\n  ],\n  \"return_data\": null,\n  \"tx\": { ... },\n  \"tx_hash\": \"0x1111111111111111111111111111111111111111111111111111111111111111\"\n}\n\n```\n\nThen we sign the transaction use `polyjuice sign-tx` and send the transaction use `ckb-cli tx send`.\n\nThen we query the balance of `0xb16ac6204aef494c411ed9dcfd6909f8c2d74527` again:\n\n```bash\necho '{\n    \"id\": 2,\n    \"jsonrpc\": \"2.0\",\n    \"method\": \"static_call\",\n    \"params\": [\n        \"0xb16ac6204aef494c411ed9dcfd6909f8c2d74527\",\n        \"0xfe68578683eb8deee4de1aca6c1ba8847c6d7691\",\n        \"0x70a08231000000000000000000000000b16ac6204aef494c411ed9dcfd6909f8c2d74527\"\n    ]\n}' \\\n| tr -d '\\n' \\\n| curl -s -H 'content-type: application/json' -d @- http://localhost:8214 \\\n| jq\n```\n\n```json\n{\n  \"jsonrpc\": \"2.0\",\n  \"result\": {\n    \"logs\": [],\n    \"return_data\": \"0x000000000000000000000000000000000000000204fce5e3e2502610fffffdd5\"\n  },\n  \"id\": 2\n}\n```\n\nWe can see the balance changed:\n\n```\nFrom:\n0x000000000000000000000000000000000000000204fce5e3e250261100000000\n\nTo:\n0x000000000000000000000000000000000000000204fce5e3e2502610fffffdd5\n```\n\nAnd query the balance of `0x3d2a2c5afeb6ba873844581245325d7cbc890313`:\n\n```bash\necho '{\n    \"id\": 2,\n    \"jsonrpc\": \"2.0\",\n    \"method\": \"static_call\",\n    \"params\": [\n        \"0xb16ac6204aef494c411ed9dcfd6909f8c2d74527\",\n        \"0xfe68578683eb8deee4de1aca6c1ba8847c6d7691\",\n        \"0x70a082310000000000000000000000003d2a2c5afeb6ba873844581245325d7cbc890313\"\n    ]\n}' \\\n| tr -d '\\n' \\\n| curl -s -H 'content-type: application/json' -d @- http://localhost:8214 \\\n| jq\n```\n\n```json\n{\n  \"jsonrpc\": \"2.0\",\n  \"result\": {\n    \"logs\": [],\n    \"return_data\": \"0x000000000000000000000000000000000000000000000000000000000000022b\"\n  },\n  \"id\": 2\n}\n```\n\n\n# The JSON-RPC API\n\n## RPC methods:\n\n``` rust\n/// Create a contract\nfn create(sender: H160, code: Bytes, value: u64) -\u003e TransactionReceipt;\n\n/// Call a contract\nfn call(sender: H160, contract_address: H160, input: Bytes, value: u64) -\u003e TransactionReceipt;\n\n/// Static call a contract\nfn static_call(sender: H160, contract_address: H160, input: Bytes) -\u003e StaticCallResponse;\n\n/// Get the code of a contract\nfn get_code(contract_address: H160) -\u003e ContractCodeJson;\n\n/// Get contract list\nfn get_contracts(from_block: u64, to_block: Option\u003cu64\u003e) -\u003e Vec\u003cContractMetaJson\u003e;\n\n/// Get contract change record\nfn get_change(contract_address: H160, block_number: Option\u003cu64\u003e) -\u003e ContractChangeJson;\n\n/// Get contract execution logs\nfn get_logs(\n  from_block: u64,\n  to_block: Option\u003cu64\u003e,\n  address: Option\u003cH160\u003e,\n  filter_topics: Option\u003cVec\u003cH256\u003e\u003e,\n  limit: Option\u003cu32\u003e,\n) -\u003e Vec\u003cLogInfo\u003e;\n\n/// Get balance of an account\nfn get_balance(\u0026self, address: H160) -\u003e u64;\n```\n\n## Response data structures:\n\n``` rust\nstruct TransactionReceipt {\n    tx: CkbTransaction,\n    tx_hash: H256,\n    entrance_contract: H160,\n    /// The newly created contract's address\n    created_addresses: Vec\u003cH160\u003e,\n    /// Destructed contract addresses\n    destructed_addresses: Vec\u003cH160\u003e,\n    logs: Vec\u003cLogEntry\u003e,\n    return_data: Option\u003cBytes\u003e,\n}\n\nstruct StaticCallResponse {\n    return_data: Bytes,\n    logs: Vec\u003cLogEntry\u003e,\n}\n\nstruct ContractMetaJson {\n    /// The block where the contract created\n    block_number: u64,\n    /// The contract address\n    address: H160,\n\n    /// The contract code\n    code: Bytes,\n    /// The contract code hash\n    code_hash: H256,\n    /// The hash of the transaction where the contract created\n    tx_hash: H256,\n    /// The output index of the transaction where the contract created\n    output_index: u32,\n    /// If the contract is destructed\n    destructed: bool,\n}\n\nstruct ContractChangeJson {\n    tx_origin: H160,\n    address: H160,\n    /// Block number\n    number: u64,\n    /// Transaction index in current block\n    tx_index: u32,\n    /// Output index in current transaction\n    output_index: u32,\n    tx_hash: H256,\n    new_storage: Vec\u003c(H256, H256)\u003e,\n    logs: Vec\u003c(Vec\u003cH256\u003e, Bytes)\u003e,\n    /// The change is create the contract\n    is_create: bool,\n}\n\nstruct ContractCodeJson {\n    code: Bytes,\n    /// The hash of the transaction where the contract created\n    tx_hash: H256,\n    /// The output index of the transaction where the contract created\n    output_index: u32,\n}\n\nstruct LogInfo {\n    block_number: u64,\n    tx_index: u32,\n    log: LogEntry,\n}\n\nstruct LogEntry {\n    address: H160,\n    topics: Vec\u003cH256\u003e,\n    data: Bytes,\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnervosnetwork%2Fpolyjuice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnervosnetwork%2Fpolyjuice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnervosnetwork%2Fpolyjuice/lists"}