{"id":13759587,"url":"https://github.com/crytic/tayt","last_synced_at":"2025-05-01T15:30:33.209Z","repository":{"id":44093490,"uuid":"503852048","full_name":"crytic/tayt","owner":"crytic","description":"StarkNet smart contract fuzzer","archived":true,"fork":false,"pushed_at":"2022-07-08T09:39:02.000Z","size":62,"stargazers_count":78,"open_issues_count":0,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-30T05:32:16.945Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/crytic.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":"2022-06-15T16:57:16.000Z","updated_at":"2025-02-14T16:18:43.000Z","dependencies_parsed_at":"2022-09-23T03:20:33.728Z","dependency_job_id":null,"html_url":"https://github.com/crytic/tayt","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/crytic%2Ftayt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crytic%2Ftayt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crytic%2Ftayt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crytic%2Ftayt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/crytic","download_url":"https://codeload.github.com/crytic/tayt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251898503,"owners_count":21661838,"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-03T13:00:55.756Z","updated_at":"2025-05-01T15:30:31.903Z","avatar_url":"https://github.com/crytic.png","language":"Python","funding_links":[],"categories":["dApps directory"],"sub_categories":["Fuzzing Tools"],"readme":"# Tayt\n\nTayt is a StarkNet smart contract fuzzer.\n\n## Installation\n\nWe recommend using a Python [`virtual environment`](https://docs.python.org/3/library/venv.html).\n```bash\ngit clone https://github.com/crytic/tayt.git \u0026\u0026 cd tayt\npython setup.py install\n```\nIf you don't have cairo-lang already installed and you are on MacOS you may have an error about a missing gmp.h file even if you executed `brew install gmp`.\nThe following command can be used to solve it.\n```bash\nCFLAGS=-I`brew --prefix gmp`/include LDFLAGS=-L`brew --prefix gmp`/lib pip install ecdsa fastecdsa sympy\n```\nIf the above command doesn't work you can find more solutions [`here`](https://github.com/OpenZeppelin/nile/issues/22).\n\n## Usage\n\nRun with default options.\n```bash\ntayt tests/flags.cairo\n```\nWhen starting you will see the properties to be checked and the external functions used to generate a sequence of transactions.\n```\nFuzzing the following properties:\n\ttayt_flag1\nExternal functions:\n\tset0\n\tset1\n```\nEventually if a property is violated a call sequence will be presented with the order of functions to be called, the respective arguments passed, the caller address, and the events emitted represented by a starting `E`.\n```\n[!] tayt_flag1 violated\nCall sequence:\n\tset0[0] from 1\n\t E set_flag0[0]\n\tset1[97066683862585213645535248899637309600] from 0\n\t E set_flag1[97066683862585213645535248899637309600]\n```\n\nThe full help menu is:\n```\nusage: tayt [-h] [--seq-len SEQ_LEN] [--blacklist-function BLACKLIST_FUNCTION [BLACKLIST_FUNCTION ...]]\n            [--psender PSENDER] [--sender SENDER [SENDER ...]] [--cairo-path CAIRO_PATH [CAIRO_PATH ...]]\n            [--coverage] [--no-shrink] [--get-class-hash] [--declare DECLARE [DECLARE ...]]\n            filename\n\nStarkNet smart contract fuzzer.\n\npositional arguments:\n  filename              Cairo file to analyze.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --seq-len SEQ_LEN     Number of transactions to generate during testing. (default: 10)\n  --blacklist-function BLACKLIST_FUNCTION [BLACKLIST_FUNCTION ...]\n                        Function name (space separated) to blacklist from execution.\n  --psender PSENDER     Address of the sender for property transactions. (default: 1)\n  --sender SENDER [SENDER ...]\n                        Addresses (space separated) to use for the transactions sent during testing.\n                        (default: [0, 1, 2])\n  --cairo-path CAIRO_PATH [CAIRO_PATH ...]\n                        A list of directories, separated by space to resolve import paths.\n  --coverage            Output a coverage file.\n  --no-shrink           Avoid shrinking failing sequences.\n  --get-class-hash      Get the class hash to use with a deploy function.\n  --declare DECLARE [DECLARE ...]\n                        A list of contracts that will be declared.\n```\n\n### Writing invariants\n\nInvariants are StarkNet view functions with names that begin with `tayt_`, have no arguments, and return a felt. An invariant is considered failed when it returns 0.\n\n```cairo\n@view\nfunc tayt_flag{\n        range_check_ptr,\n        syscall_ptr: felt*,\n        pedersen_ptr: HashBuiltin*\n    }() -\u003e (res: felt):\n    let (flag_result) = flag.read()\n    if flag_result == 1:\n        return (0)\n    end\n    return (1)\nend\n```\n\nIf the flag storage variable is set to 1 the invariant will fail.\n\n### How to test a contract that deploys other contracts\n\nWe will use `test/deploy.cairo` as an example of a contract that deploys other contracts.\nFirst we have to get the class hash of the contracts we want to deploy:\n\nIn our case we will deploy `test/flags.cairo`.\n```bash\ntayt --get-class-hash tests/flags.cairo\n```\nWe will get the class hash to use in the [`deploy`](https://starknet.io/docs/hello_starknet/deploying_from_contracts.html#the-deploy-system-call) function.\n```\nClass hash for tests/flags.cairo\n2024779828085525422431444182955849544076259995530386260630136607064428821244\n```\nFinally we can test `deploy.cairo`, the `--declare` option takes a list of contracts to declare in the fuzzing state.\n```\ntayt tests/deploy.cairo --declare tests/flags.cairo\n```\n\n### Coverage\n\nWhen the `--coverage` option is enabled, a file named covered.{time}.txt which contains the source code with coverage annotations will be saved. A line starting with `*` has been executed at least once.\n\nExample with `tests/flags.cairo`:\n\n```cairo\n@external\n*func set1{\n*        syscall_ptr: felt*,\n*        pedersen_ptr: HashBuiltin*,\n*        range_check_ptr,\n*        ecdsa_ptr: SignatureBuiltin*\n*    }(val: felt):\n*    let (res, remainder) = unsigned_div_rem(val, 10)\n*    if remainder == 0:\n*        let (flag_0) = flag0.read()\n*        if flag_0 == 1:\n*            flag1.write(1)\n*            set_flag1.emit(val)\n*            return ()\n        end\n*        return ()\n    end\n*    return()    \nend\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrytic%2Ftayt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrytic%2Ftayt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrytic%2Ftayt/lists"}