{"id":22191961,"url":"https://github.com/cryptape/teth","last_synced_at":"2025-08-03T03:39:59.356Z","repository":{"id":62558847,"uuid":"68271455","full_name":"cryptape/teth","owner":"cryptape","description":"Testing and deployment framework for Ethereum smart contracts.","archived":false,"fork":false,"pushed_at":"2016-09-19T14:04:42.000Z","size":109,"stargazers_count":36,"open_issues_count":4,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-06-22T12:49:21.160Z","etag":null,"topics":["ethereum","test"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cryptape.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}},"created_at":"2016-09-15T06:26:19.000Z","updated_at":"2023-08-30T13:09:39.000Z","dependencies_parsed_at":"2022-11-03T11:15:19.839Z","dependency_job_id":null,"html_url":"https://github.com/cryptape/teth","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/cryptape/teth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cryptape%2Fteth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cryptape%2Fteth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cryptape%2Fteth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cryptape%2Fteth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cryptape","download_url":"https://codeload.github.com/cryptape/teth/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cryptape%2Fteth/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266523750,"owners_count":23942794,"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-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"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":["ethereum","test"],"created_at":"2024-12-02T12:18:32.118Z","updated_at":"2025-07-26T22:31:48.232Z","avatar_url":"https://github.com/cryptape.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Introduction\nTeth is a Ethereum smart contract test framework in ruby.It provides two testing environments: testing in ruby EVM and testing in geth.You don't need to understand ruby grammar, just enjoy syntactic sugar.\n\n## Dependencies\n- Solidity\n- Ruby ~\u003e 2.2.2\n- [ruby-bitcoin-secp256k1](https://github.com/cryptape/ruby-bitcoin-secp256k1)\n- Go-ethereum ~\u003e 1.4.11\n\n## Install\n```shell\nbundle install teth\n```\n\n## How to use\n\n#### Help command\n```\n$ teth\nUsage: teth COMMAND [ARGS]\nThe most common teth commands are:\n  new         Create a new Smart Contract application. \"teth new my_app\" creates a\n              new application called my_app in \"./my_app\" (short-cut alias: \"n\")\n  generate    Generate new solidity smart contract and test files. \"teth generate token\"\n              creates Token contract and corresponding test files. (short-cut alias: \"g\")\n  test        Run your ruby tests in ruby evm. (short-cut alias: \"t\")\n  init        Bootstraps and initialises a new genesis block. \"teth init\" creates data directory\n              for private chain.(short-cut alias: \"i\")\n  import_keys Import keys to private chain (short-cut alias: \"ik\")\n  build       Build contract (short-cut alias: \"b\")\n  migrate     Deploy contract on private chain (short-cut alias: \"m\")\n  server      Start geth server (short-cut alias: \"s\")\n  console     Start geth attach (short-cut alias: \"c\")\n  gtest       Run your javascript tests on geth (short-cut alias: \"gt\")\n\nAll commands can be run with -h (or --help) for more information.\n\n```\n#### Creeat project\nCreate a new Smart Contract application\n```shell\n$ teth n examples\nCreating project examples...\nResolving dependencies...\nUsing ffi 1.9.14\nUsing little-plugger 1.1.4\nUsing multi_json 1.12.1\nUsing digest-sha3 1.1.0\nUsing ethash 0.2.0\nUsing fiddler-rb 0.1.2\nUsing lru_redux 1.1.0\nUsing minitest 5.9.0\nUsing rlp 0.7.3\nUsing bundler 1.12.5\nUsing bitcoin-secp256k1 0.4.0\nUsing logging 2.1.0\nUsing leveldb 0.1.9\nUsing block_logger 0.1.2\nUsing ruby-ethereum 0.9.5\nUsing teth 0.1.1\nBundle complete! 1 Gemfile dependency, 16 gems now installed.\nUse `bundle show [gemname]` to see where a bundled gem is installed.\nDone.\n\n$ cd examples\n```\n#### Generate new Smart Contract and test files\n```shell\n$ teth g token\nCreating Token contract file...\nCreating token test files...\nDone.\n```\nThis generates contract file `contracts/Token.sol`, and test files `tests/token_test.rb`, `gtests/Token_test.js`.\n\nEdit token contract and test file.\n\n`contracts/Token.sol`\n```javascript\npragma solidity ^0.4.0;\n\ncontract Token {\n    address issuer;\n    mapping (address =\u003e uint) balances;\n\n    event Issue(address account, uint amount);\n    event Transfer(address from, address to, uint amount);\n\n    function Token() {\n        issuer = msg.sender;\n    }\n\n    function issue(address account, uint amount) {\n        if (msg.sender != issuer) throw;\n        balances[account] += amount;\n        Issue(account, amount);\n    }\n\n    function transfer(address to, uint amount) {\n        if (balances[msg.sender] \u003c amount) throw;\n\n        balances[msg.sender] -= amount;\n        balances[to] += amount;\n\n        Transfer(msg.sender, to, amount);\n    }\n\n    function getBalance(address account) constant returns (uint) {\n        return balances[account];\n    }\n}\n\n```\n\n`tests/token_test.rb`\n```ruby\nrequire 'teth/minitest'\n\nclass TokenTest \u003c Teth::Minitest\n  def test_contract_deployed\n    assert_equal false, contract.address.nil?\n  end\n\n  def test_issue_balance\n    assert_equal 0, contract.getBalance(bob)\n    contract.issue bob, 100\n    assert_equal 100, contract.getBalance(bob)\n  end\n\n  def test_issue_exception\n    assert_raises(TransactionFailed) do\n      contract.issue bob, 100, sender: eve_privkey\n    end\n    assert_equal 0, contract.getBalance(bob)\n  end\n\n  def test_token_transfer\n    contract.issue bob, 100\n    contract.transfer carol, 90, sender: bob_privkey\n    assert_equal 90, contract.getBalance(carol)\n\n    assert_raises(TransactionFailed) { contract.transfer carol, 90, sender: bob_privkey }\n  end\nend\n\n```\n\n#### Run tests in ruby evm\n```shell\n$ teth t token\nTest Token contract...\nRun options: --seed 2192\n\n# Running:\n\n....\n\nFinished in 1.935546s, 2.0666 runs/s, 3.6166 assertions/s.\n\n4 runs, 7 assertions, 0 failures, 0 errors, 0 skips\nDone.\n```\n\n#### Unit tests\nYou can wirte fast, simple tests.\n```ruby\nrequire 'teth/minitest'\n\nclass TokenTest \u003c Teth::Minitest\n  def test_contract_deployed\n    assert_equal false, contract.address.nil?\n  end\n\n  def test_issue_balance\n    assert_equal 0, contract.getBalance(bob)\n    contract.issue bob, 100\n    assert_equal 100, contract.getBalance(bob)\n  end\n\n  def test_issue_exception\n    assert_raises(TransactionFailed) do\n      contract.issue bob, 100, sender: eve_privkey\n    end\n    assert_equal 0, contract.getBalance(bob)\n  end\n\n  def test_token_transfer\n    contract.issue bob, 100\n    contract.transfer carol, 90, sender: bob_privkey\n    assert_equal 90, contract.getBalance(carol)\n\n    assert_raises(TransactionFailed) { contract.transfer carol, 90, sender: bob_privkey }\n  end\nend\n\n```\nMore details:\nhttps://github.com/seattlerb/minitest\n\n#### Init geth block\n```shell\n$ teth init\nInitialising a new genesis block...\n***** Using geth at: geth\nI0917 16:01:17.338908 ethdb/database.go:82] Alloted 16MB cache and 16 file handles to /Users/u2/cryptape/teth/examples/data/chaindata\nI0917 16:01:17.347151 cmd/geth/main.go:299] successfully wrote genesis block and/or chain rule set: 611596e7979cd4e7ca1531260fa706093a5492ecbdf58f20a39545397e424d04\n```\n#### Import keys to geth\n```shell\n$ teth ik\nImporting keys, this will take a while, please be patient......\n***** Using geth at: geth\n***** Import all pre-funded private keys\nNotice: No need to input your password. The default password is 123456\nspawn geth --datadir data account import ./private_keys/3ae88fe370c39384fc16da2c9e768cf5d2495b48.key\nYour new account is locked with a password. Please give a password. Do not forget this password.\nPassphrase:\nRepeat passphrase:\nAddress: {3ae88fe370c39384fc16da2c9e768cf5d2495b48}\nNotice: No need to input your password. The default password is 123456\nspawn geth --datadir data account import ./private_keys/81063419f13cab5ac090cd8329d8fff9feead4a0.key\nYour new account is locked with a password. Please give a password. Do not forget this password.\nPassphrase:\nRepeat passphrase:\nAddress: {81063419f13cab5ac090cd8329d8fff9feead4a0}\nNotice: No need to input your password. The default password is 123456\nspawn geth --datadir data account import ./private_keys/9da26fc2e1d6ad9fdd46138906b0104ae68a65d8.key\nYour new account is locked with a password. Please give a password. Do not forget this password.\nPassphrase:\nRepeat passphrase:\nAddress: {9da26fc2e1d6ad9fdd46138906b0104ae68a65d8}\n***** Done.\n\n```\nNotice: *This will take a while, please be patient. No need to input your password.*\n\n#### Build contract\n```shell\n$ teth build token\nBuilding contract Token\n\n======= Token =======\nGas estimation:\nconstruction:\n   20201 + 73400 = 93601\nexternal:\n\n\n-------------------------------------\nEnter Gas:\n400000\nEnter Value To Be Transferred:\n\nEnter Input:\n\nDone.\n```\nBuild all contracts if no contract name provided.\n\n#### Start geth server\n```shell\n$ teth server\n***** Using geth at: geth\nStart geth server...\nI0917 16:17:16.882572 ethdb/database.go:82] Alloted 128MB cache and 1024 file handles to data/chaindata\nI0917 16:17:16.894415 ethdb/database.go:169] closed db:data/chaindata\nI0917 16:17:16.895446 ethdb/database.go:82] Alloted 128MB cache and 1024 file handles to data/chaindata\nI0917 16:17:16.946341 eth/backend.go:621] upgrading db log bloom bins\nI0917 16:17:16.946478 eth/backend.go:629] upgrade completed in 142.276µs\nI0917 16:17:16.946513 ethdb/database.go:82] Alloted 16MB cache and 16 file handles to data/dapp\nI0917 16:17:16.951072 eth/backend.go:172] Protocol Versions: [63 62], Network Id: 31415926\nI0917 16:17:16.951142 eth/backend.go:201] Blockchain DB Version: 3\nI0917 16:17:16.953641 core/blockchain.go:206] Last header: #0 [611596e7…] TD=131072\nI0917 16:17:16.953667 core/blockchain.go:207] Last block: #0 [611596e7…] TD=131072\nI0917 16:17:16.953678 core/blockchain.go:208] Fast block: #0 [611596e7…] TD=131072\nI0917 16:17:16.954420 p2p/server.go:313] Starting Server\nI0917 16:17:16.955324 p2p/server.go:556] Listening on [::]:30303\nI0917 16:17:16.957427 node/node.go:296] IPC endpoint opened: data/geth.ipc\nI0917 16:17:16.959797 node/node.go:366] HTTP endpoint opened: http://localhost:8545\nI0917 16:17:17.945231 cmd/geth/accountcmd.go:189] Unlocked account 3ae88fe370c39384fc16da2c9e768cf5d2495b48\nI0917 16:17:19.158064 p2p/nat/nat.go:111] mapped network port tcp:30303 -\u003e 30303 (ethereum p2p) using UPNP IGDv1-IP1\n```\n#### Migrate\nDeploy your contract on geth, must keep teth sever started.\n```shell\n$ teth m\nMigrating contract token\n***** Using geth at: geth\nnull\nContract transaction send: TransactionHash: 0x3a9ca7a774a4bc5b3ba23b57f3c65a5debbfcbba422f902009909604ee668a63 waiting to be mined...\nCompiled Object : TokenCompiled\nContract : TokenContract\nContract Instance : Token\ntrue\nContract mined! Address: 0x3a020580345e79e223580d8d6a50e063667f19b5\nDone.\n\n```\nThis deploys contract on geth, and creates two files.One is `temp/db/Token.json` which keeps abi and address.\n```json\n{\n  \"Token\": {\n    \"abi\": [\n      {\n        \"constant\": false,\n        \"inputs\": [\n          {\n            \"name\": \"account\",\n            \"type\": \"address\"\n          },\n          {\n            \"name\": \"amount\",\n            \"type\": \"uint256\"\n          }\n        ],\n        \"name\": \"issue\",\n        \"outputs\": [\n\n        ],\n        \"payable\": false,\n        \"type\": \"function\"\n      },\n      {\n        \"constant\": false,\n        \"inputs\": [\n          {\n            \"name\": \"to\",\n            \"type\": \"address\"\n          },\n          {\n            \"name\": \"amount\",\n            \"type\": \"uint256\"\n          }\n        ],\n        \"name\": \"transfer\",\n        \"outputs\": [\n\n        ],\n        \"payable\": false,\n        \"type\": \"function\"\n      },\n      {\n        \"constant\": true,\n        \"inputs\": [\n          {\n            \"name\": \"account\",\n            \"type\": \"address\"\n          }\n        ],\n        \"name\": \"getBalance\",\n        \"outputs\": [\n          {\n            \"name\": \"\",\n            \"type\": \"uint256\"\n          }\n        ],\n        \"payable\": false,\n        \"type\": \"function\"\n      },\n      {\n        \"inputs\": [\n\n        ],\n        \"type\": \"constructor\"\n      },\n      {\n        \"anonymous\": false,\n        \"inputs\": [\n          {\n            \"indexed\": false,\n            \"name\": \"account\",\n            \"type\": \"address\"\n          },\n          {\n            \"indexed\": false,\n            \"name\": \"amount\",\n            \"type\": \"uint256\"\n          }\n        ],\n        \"name\": \"Issue\",\n        \"type\": \"event\"\n      },\n      {\n        \"anonymous\": false,\n        \"inputs\": [\n          {\n            \"indexed\": false,\n            \"name\": \"from\",\n            \"type\": \"address\"\n          },\n          {\n            \"indexed\": false,\n            \"name\": \"to\",\n            \"type\": \"address\"\n          },\n          {\n            \"indexed\": false,\n            \"name\": \"amount\",\n            \"type\": \"uint256\"\n          }\n        ],\n        \"name\": \"Transfer\",\n        \"type\": \"event\"\n      }\n    ],\n    \"bin\": \"0x606060405260008054600160a060020a0319163317905561016f806100246000396000f3606060405260e060020a6000350463867904b48114610034578063a9059cbb1461005e578063f8b2cb4f14610092575b610002565b34610002576100bc600435602435600054600160a060020a0390811633909116146100be57610002565b34610002576100bc60043560243533600160a060020a03166000908152600160205260409020548190101561010f57610002565b3461000257600160a060020a03600435166000908152600160205260409020546060908152602090f35b005b600160a060020a03821660008181526001602052604090819020805484019055606091825260808390527fc65a3f767206d2fdcede0b094a4840e01c0dd0be1888b5ba800346eaa0123c1691a15050565b6040600081812080548490039055600160a060020a03808516808352929091208054840190553316606090815260809190915260a08290527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9080a1505056\",\n    \"devdoc\": {\n      \"methods\": {\n      }\n    },\n    \"userdoc\": {\n      \"methods\": {\n      }\n    }\n  },\n  \"address\": \"0x3a020580345e79e223580d8d6a50e063667f19b5\"\n}\n```\nAnother is `temp/migrations/Token.js`\n```javascript\nvar TokenContract = web3.eth.contract([{\"constant\":false, \"inputs\":[{\"name\":\"account\", \"type\":\"address\"}, {\"name\":\"amount\", \"type\":\"uint256\"}], \"name\":\"issue\", \"outputs\":[], \"payable\":false, \"type\":\"function\"}, {\"constant\":false, \"inputs\":[{\"name\":\"to\", \"type\":\"address\"}, {\"name\":\"amount\", \"type\":\"uint256\"}], \"name\":\"transfer\", \"outputs\":[], \"payable\":false, \"type\":\"function\"}, {\"constant\":true, \"inputs\":[{\"name\":\"account\", \"type\":\"address\"}], \"name\":\"getBalance\", \"outputs\":[{\"name\":\"\", \"type\":\"uint256\"}], \"payable\":false, \"type\":\"function\"}, {\"inputs\":[], \"type\":\"constructor\"}, {\"anonymous\":false, \"inputs\":[{\"indexed\":false, \"name\":\"account\", \"type\":\"address\"}, {\"indexed\":false, \"name\":\"amount\", \"type\":\"uint256\"}], \"name\":\"Issue\", \"type\":\"event\"}, {\"anonymous\":false, \"inputs\":[{\"indexed\":false, \"name\":\"from\", \"type\":\"address\"}, {\"indexed\":false, \"name\":\"to\", \"type\":\"address\"}, {\"indexed\":false, \"name\":\"amount\", \"type\":\"uint256\"}], \"name\":\"Transfer\", \"type\":\"event\"}]);\n\nvar Token = TokenContract.at('0x80d29fb7f81d2ccd77c708b6135389c9c08653dc');\n\n```\nDeploy all contracts if no contract name provided.\n\n#### Write your own javascript test\n`gtests/Token_test.js`\n```javascript\nloadScript('temp/migrations/Token.js');\n\nvar balance = Token.getBalance.call(web3.eth.accounts[0], { from: web3.eth.accounts[0] })\n\nconsole.log(\"balance is: \", balance);\n\nToken.issue.sendTransaction(web3.eth.accounts[0], 10000, { from: web3.eth.accounts[0] }, function(err, tx){\n  if(err){\n    console.log(\"issue error!\");\n  } else {\n    console.log(\"issue success. tx: \", tx);\n  }\n})\n\nminer.start();admin.sleepBlocks(2);miner.stop();\n\nbalance = Token.getBalance.call(web3.eth.accounts[0], { from: web3.eth.accounts[0] })\n\nconsole.log(\"balance is: \", balance);\n\n```\n\n#### Run gtest\n```\n$ teth gt token\n***** Using geth at: geth\nTesting contract Token...\nbalance is:  0\nissue success. tx:  0x7fd24d1903345d4f70208c41fc3a1bd71be63f8dd7db7c654f2d3a7c176b4031\nbalance is:  10000\ntrue\nDone.\n```\n\n:beers:\n\n## Frequently Asked Questions\n\n#### Error: Account does not exist or account balance too low while `teth migrate token`\nThis is just low balance for your accoutns. Just mining for a while will be ok.\n```shell\n$ teth c\n***** Using geth at: geth\nStarting geth attach...\nWelcome to the Geth JavaScript console!\n\ninstance: Geth/v1.4.11-stable-fed692f6/darwin/go1.7\ncoinbase: 0x3ae88fe370c39384fc16da2c9e768cf5d2495b48\nat block: 3 (Sat, 17 Sep 2016 17:42:50 CST)\n datadir: data\n modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0\n\n\u003e miner.start()\ntrue\n\u003e web3.eth.getBalance(web3.eth.accounts[0])\n506406250000000000000\n\u003e \n\n```\n\n\n## TODO:\n\n- Add chai for js test\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcryptape%2Fteth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcryptape%2Fteth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcryptape%2Fteth/lists"}