├── .envrc ├── .github ├── pull_request_template.md ├── scripts │ ├── build-macos-release.sh │ ├── host.sh │ ├── install-cvc4.sh │ ├── install-libff.sh │ ├── install-libsecp256k1.sh │ ├── install-solc.sh │ └── install-z3.sh └── workflows │ ├── build.yml │ └── release.yml ├── .gitignore ├── .gitmodules ├── ARCHITECTURE.md ├── README.md ├── default.nix ├── flake.lock ├── flake.nix ├── haskell.nix ├── nix ├── LICENSE ├── build-dapp-package.nix ├── dapptools-src.nix ├── geth.nix ├── hevm-tests │ ├── default.nix │ ├── smt-checker.nix │ └── yul-equivalence.nix ├── libff.nix ├── make-solc-static.sh ├── solc-static-versions.nix ├── solc-static.nix ├── solc-updates.md ├── solc-versions.nix ├── solidity-package.nix └── solidity-package.sh ├── overlay.nix ├── release.nix └── src ├── dapp-tests ├── .gitignore ├── Makefile ├── default.nix ├── fail │ ├── cheatCodes.sol │ ├── dsProveFail.sol │ └── invariantFail.sol ├── genesis.json ├── integration │ ├── contracts │ │ ├── AB.sol │ │ ├── dstoken.bin-runtime │ │ ├── factor.sol │ │ ├── stateful.sol │ │ └── token.sol │ ├── diff-fuzz.py │ └── tests.sh ├── pass │ ├── abstract.sol │ ├── cheatCodes.sol │ ├── constantinople.sol │ ├── dsProvePass.sol │ ├── invariants.sol │ └── libraries.sol └── shell.nix ├── dapp ├── .gitignore ├── .gitmodules ├── .travis-test ├── .travis.yml ├── CHANGELOG.md ├── COPYING ├── Dockerfile ├── Makefile ├── README.md ├── bin │ └── dapp ├── default.nix ├── libexec │ └── dapp │ │ ├── dapp │ │ ├── dapp---find-libraries │ │ ├── dapp---find-test-methods │ │ ├── dapp---hevm-opts │ │ ├── dapp---make-cache │ │ ├── dapp---make-library-state │ │ ├── dapp---nix-run │ │ ├── dapp---parse-deps │ │ ├── dapp---sanity │ │ ├── dapp---testnet-launch │ │ ├── dapp---use │ │ ├── dapp---version │ │ ├── dapp-address │ │ ├── dapp-build │ │ ├── dapp-build-legacy │ │ ├── dapp-check-snapshot │ │ ├── dapp-clean │ │ ├── dapp-clone │ │ ├── dapp-create │ │ ├── dapp-debug │ │ ├── dapp-help │ │ ├── dapp-init │ │ ├── dapp-install │ │ ├── dapp-mk-standard-json │ │ ├── dapp-remappings │ │ ├── dapp-selftest │ │ ├── dapp-snapshot │ │ ├── dapp-test │ │ ├── dapp-test-geth-experimental │ │ ├── dapp-test-standalone │ │ ├── dapp-testnet │ │ ├── dapp-uninstall │ │ ├── dapp-update │ │ ├── dapp-upgrade │ │ ├── dapp-verify │ │ ├── dapp-verify-contract │ │ └── dapp-version └── resources │ └── jsontemplate.json ├── ethsign ├── CHANGELOG ├── COPYING ├── README.md ├── default.nix ├── ethsign.go └── go.mod ├── hevm ├── .dir-locals.el ├── .envrc ├── .gitignore ├── .hlint.yaml ├── .travis.yml ├── CHANGELOG.md ├── COPYING ├── Dockerfile ├── Makefile ├── README.md ├── Setup.hs ├── benchmark │ └── benchmark.hs ├── ethjet │ ├── blake2.cc │ ├── blake2.h │ ├── ethjet-ff.cc │ ├── ethjet-ff.h │ ├── ethjet.c │ ├── ethjet.h │ ├── tinykeccak.c │ └── tinykeccak.h ├── hevm-cli │ └── hevm-cli.hs ├── hevm.cabal ├── hevm.el ├── hie.yaml ├── run-blockchain-tests ├── run-consensus-tests ├── shell.nix ├── src │ ├── EVM.hs │ └── EVM │ │ ├── ABI.hs │ │ ├── Concrete.hs │ │ ├── Dapp.hs │ │ ├── Debug.hs │ │ ├── Demand.hs │ │ ├── Dev.hs │ │ ├── Emacs.hs │ │ ├── Exec.hs │ │ ├── Facts.hs │ │ ├── Facts │ │ └── Git.hs │ │ ├── FeeSchedule.hs │ │ ├── Fetch.hs │ │ ├── Flatten.hs │ │ ├── Format.hs │ │ ├── Hexdump.hs │ │ ├── Op.hs │ │ ├── Patricia.hs │ │ ├── Precompiled.hs │ │ ├── RLP.hs │ │ ├── Solidity.hs │ │ ├── Stepper.hs │ │ ├── StorageLayout.hs │ │ ├── SymExec.hs │ │ ├── Symbolic.hs │ │ ├── TTY.hs │ │ ├── TTYCenteredList.hs │ │ ├── Transaction.hs │ │ ├── Types.hs │ │ ├── UnitTest.hs │ │ └── VMTest.hs ├── stack.yaml └── test │ └── test.hs ├── jays ├── .gitignore ├── LICENSE ├── Main.hs ├── Makefile ├── Setup.hs ├── jays.cabal ├── shell.nix ├── src │ └── Jays.hs └── test │ └── Test.hs ├── restless-git ├── .gitignore ├── COPYING ├── Makefile ├── README.md ├── restless-git.cabal ├── shell.nix ├── src │ └── Restless │ │ └── Git.hs └── test │ └── Test.hs ├── seth ├── CHANGELOG.md ├── COPYING ├── Makefile ├── README.md ├── TODO ├── bin │ └── seth ├── default.nix └── libexec │ └── seth │ ├── ethers.min.js │ ├── seth │ ├── seth---abi-constructor │ ├── seth---abi-decode │ ├── seth---abi-event-json │ ├── seth---abi-function-json │ ├── seth---calldata-decode │ ├── seth---decode-event │ ├── seth---decode-events │ ├── seth---decorate-abi │ ├── seth---event-name │ ├── seth---fail │ ├── seth---fail-usage │ ├── seth---field │ ├── seth---from-ascii │ ├── seth---from-bin │ ├── seth---from-fix │ ├── seth---from-wei │ ├── seth---help │ ├── seth---max-int │ ├── seth---max-uint │ ├── seth---min-int │ ├── seth---nix-run │ ├── seth---send-params │ ├── seth---show-json │ ├── seth---to-address │ ├── seth---to-ascii │ ├── seth---to-bytes32 │ ├── seth---to-checksum-address │ ├── seth---to-dec │ ├── seth---to-fix │ ├── seth---to-hex │ ├── seth---to-hexdata │ ├── seth---to-int256 │ ├── seth---to-uint256 │ ├── seth---to-wei │ ├── seth---to-word │ ├── seth---use │ ├── seth---version │ ├── seth---warn │ ├── seth-4byte │ ├── seth-4byte-decode │ ├── seth-4byte-event │ ├── seth-abi │ ├── seth-abi-encode │ ├── seth-accounts │ ├── seth-age │ ├── seth-balance │ ├── seth-basefee │ ├── seth-block │ ├── seth-block-number │ ├── seth-bundle-source │ ├── seth-call │ ├── seth-calldata │ ├── seth-chain │ ├── seth-chain-id │ ├── seth-client │ ├── seth-code │ ├── seth-curl │ ├── seth-debug │ ├── seth-estimate │ ├── seth-etherscan-source │ ├── seth-events │ ├── seth-gas-price │ ├── seth-get-block-by-hash │ ├── seth-get-block-by-number │ ├── seth-get-full-block-by-hash │ ├── seth-get-full-block-by-number │ ├── seth-get-tx-by-hash │ ├── seth-hashrate │ ├── seth-help │ ├── seth-index │ ├── seth-keccak │ ├── seth-keccak-rpc │ ├── seth-listening │ ├── seth-logs │ ├── seth-logs-etherscan │ ├── seth-logs-follow │ ├── seth-logs-rpc │ ├── seth-lookup │ ├── seth-lookup-address │ ├── seth-ls │ ├── seth-mining │ ├── seth-mktx │ ├── seth-namehash │ ├── seth-nonce │ ├── seth-publish │ ├── seth-receipt │ ├── seth-resolve-name │ ├── seth-rpc │ ├── seth-rpc-curl │ ├── seth-rpc-request │ ├── seth-run-tx │ ├── seth-send │ ├── seth-sig │ ├── seth-sign │ ├── seth-solc │ ├── seth-storage │ ├── seth-tx │ └── sha3.js ├── token ├── Makefile ├── README ├── bin │ └── token ├── default.nix ├── index.css ├── index.html ├── index.js └── libexec │ └── token │ ├── token │ ├── token---format │ ├── token---help │ ├── token-allowance │ ├── token-approve │ ├── token-balance │ ├── token-help │ ├── token-permit │ ├── token-supply │ └── token-transfer └── upload-haskell-package /.envrc: -------------------------------------------------------------------------------- 1 | use flake 2 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | ## Checklist 4 | 5 | - [ ] tested locally 6 | - [ ] added automated tests 7 | - [ ] updated the docs 8 | - [ ] updated the changelog 9 | -------------------------------------------------------------------------------- /.github/scripts/build-macos-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eux 3 | 4 | add_rpath() 5 | { 6 | BINARY="$1" 7 | install_name_tool -add_rpath "@executable_path/." "$BINARY" 8 | } 9 | 10 | fix_path() 11 | { 12 | BINARY="$1" 13 | MATCH="$2" 14 | NEW="$3" 15 | OLD=$(otool -L "$BINARY" | grep "$MATCH" | awk '{print $1}') 16 | install_name_tool -change "$OLD" "$NEW" "$BINARY" 17 | cp -n "$OLD" "$(dirname "$BINARY")/$(basename "$NEW")" || true 18 | } 19 | 20 | BUILD="$(mktemp -d)/hevm" 21 | mkdir -p "$BUILD" 22 | cp "$HOME/.local/bin/hevm" "$BUILD" 23 | 24 | BINARY="$BUILD/hevm" 25 | add_rpath "$BINARY" 26 | fix_path "$BINARY" libsecp256k1 "@rpath/libsecp256k1.dylib" 27 | fix_path "$BINARY" libff "@rpath/libff.dylib" 28 | fix_path "$BUILD/libff.dylib" libgmp "@rpath/libgmp.dylib" 29 | fix_path "$BUILD/libsecp256k1.dylib" libgmp "@rpath/libgmp.dylib" 30 | 31 | GZIP=-9 tar -czf hevm.tar.gz -C "$BUILD/.." hevm 32 | -------------------------------------------------------------------------------- /.github/scripts/host.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | if [ -z ${PREFIX+x} ]; then 4 | export PREFIX="$HOME/.local" 5 | fi 6 | 7 | if [ "$HOST_OS" = "Linux" ]; then 8 | EXT=".a" 9 | elif [ "$HOST_OS" = "macOS" ]; then 10 | EXT=".dylib" 11 | else 12 | echo "unrecognized host" 13 | exit 1 14 | fi 15 | -------------------------------------------------------------------------------- /.github/scripts/install-cvc4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | set -eux 5 | 6 | mkdir -p $HOME/.local/bin; 7 | 8 | travis_retry() { 9 | cmd=$* 10 | $cmd || (sleep 2 && $cmd) || (sleep 10 && $cmd) 11 | } 12 | 13 | fetch_cvc4_linux() { 14 | VER="$1" 15 | wget "https://github.com/CVC4/CVC4/releases/download/$VER/cvc4-$VER-x86_64-linux-opt" 16 | chmod +x "cvc4-$VER-x86_64-linux-opt" 17 | mv "cvc4-$VER-x86_64-linux-opt" "$HOME/.local/bin/cvc4" 18 | echo "Downloaded cvc4 $VER" 19 | } 20 | 21 | fetch_cvc4_macos() { 22 | VER="$1" 23 | wget "https://github.com/CVC4/CVC4/releases/download/$VER/cvc4-$VER-macos-opt" 24 | chmod +x "cvc4-$VER-macos-opt" 25 | mv "cvc4-$VER-macos-opt" "$HOME/.local/bin/cvc4" 26 | echo "Downloaded cvc4 $VER" 27 | } 28 | 29 | if [ "$HOST_OS" = "Linux" ]; then 30 | travis_retry fetch_cvc4_linux "1.8" 31 | else 32 | travis_retry fetch_cvc4_macos "1.8" 33 | fi 34 | -------------------------------------------------------------------------------- /.github/scripts/install-libff.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | set -eux 4 | 5 | source .github/scripts/host.sh 6 | 7 | if [ -f $HOME/.local/lib/libff"$EXT" ]; then 8 | echo "libff exists, exiting..." 9 | exit 0 10 | fi 11 | 12 | git clone https://github.com/scipr-lab/libff --recursive 13 | cd libff 14 | git submodule init && git submodule update 15 | git checkout v0.2.1 16 | 17 | ARGS="-DCMAKE_INSTALL_PREFIX=$PREFIX -DWITH_PROCPS=OFF" 18 | CXXFLAGS="" 19 | if [ "$HOST_OS" = "macOS" ]; then 20 | export LDFLAGS=-L/usr/local/opt/openssl/lib 21 | export CPPFLAGS=-I/usr/local/opt/openssl/include 22 | export CXXFLAGS=-I/usr/local/opt/openssl/include 23 | ARGS="$ARGS -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl/include/openssl -DCURVE=ALT_BN128 -DCMAKE_INSTALL_NAME_DIR=$PREFIX/lib" 24 | sed -i '' 's/STATIC/SHARED/' libff/CMakeLists.txt # Fix GHC segfaults from hell (idk why) 25 | sed -i '' 's/STATIC/SHARED/' depends/CMakeLists.txt 26 | fi 27 | 28 | mkdir build 29 | cd build 30 | CXXFLAGS="-fPIC $CXXFLAGS" cmake $ARGS .. 31 | make && make install 32 | -------------------------------------------------------------------------------- /.github/scripts/install-libsecp256k1.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | set -eux 4 | 5 | source .github/scripts/host.sh 6 | 7 | if [ -f $HOME/.local/lib/libsecp256k1.a ]; then 8 | echo "libsecp256k1 exists, exiting..." 9 | exit 0 10 | fi 11 | 12 | gitRef="1086fda4c1975d0cad8d3cad96794a64ec12dca4" 13 | curl -LO "https://github.com/bitcoin-core/secp256k1/archive/$gitRef.zip" 14 | 15 | unzip "$gitRef.zip" 16 | cd "secp256k1-$gitRef" 17 | 18 | ./autogen.sh 19 | # hevm needs reecovery module 20 | # enable pic so static library can link against dynamic correctly 21 | ./configure --prefix=$PREFIX --enable-module-recovery --with-pic 22 | 23 | make install 24 | -------------------------------------------------------------------------------- /.github/scripts/install-solc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | set -eux 5 | 6 | mkdir -p $HOME/.local/bin; 7 | 8 | travis_retry() { 9 | cmd=$* 10 | $cmd || (sleep 2 && $cmd) || (sleep 10 && $cmd) 11 | } 12 | 13 | fetch_solc_linux() { 14 | VER="$1" 15 | if [ ! -f "$HOME/.local/bin/solc-$VER" ]; then 16 | rm -Rf solc-static-linux 17 | wget "https://github.com/ethereum/solidity/releases/download/v$VER/solc-static-linux" 18 | chmod +x solc-static-linux 19 | mv solc-static-linux "$HOME/.local/bin/solc-$VER" 20 | echo "Downloaded solc $VER" 21 | else 22 | echo "Skipped solc $VER, already present" 23 | fi 24 | } 25 | 26 | fetch_solc_macos() { 27 | VER="$1" 28 | if [ ! -f "$HOME/.local/bin/solc-$VER" ]; then 29 | rm -Rf solc-macos 30 | wget "https://github.com/ethereum/solidity/releases/download/v$VER/solc-macos" 31 | chmod +x solc-macos 32 | mv solc-macos "$HOME/.local/bin/solc-$VER" 33 | echo "Downloaded solc $VER" 34 | else 35 | echo "Skipped solc $VER, already present" 36 | fi 37 | } 38 | 39 | if [ "$HOST_OS" = "Linux" ]; then 40 | if [ "${SOLC_VER:-}" == "" ]; then 41 | travis_retry fetch_solc_linux "0.8.6" 42 | else 43 | travis_retry fetch_solc_linux "$SOLC_VER" 44 | fi 45 | else 46 | if [ "${SOLC_VER:-}" == "" ]; then 47 | travis_retry fetch_solc_macos "0.8.6" 48 | else 49 | travis_retry fetch_solc_macos "$SOLC_VER" 50 | fi 51 | fi 52 | -------------------------------------------------------------------------------- /.github/scripts/install-z3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | set -eux 5 | 6 | mkdir -p $HOME/.local/bin; 7 | 8 | travis_retry() { 9 | cmd=$* 10 | $cmd || (sleep 2 && $cmd) || (sleep 10 && $cmd) 11 | } 12 | 13 | fetch_z3_linux() { 14 | VER="$1" 15 | wget "https://github.com/Z3Prover/z3/releases/download/z3-$VER/z3-$VER-x64-ubuntu-18.04.zip" 16 | unzip "z3-$VER-x64-ubuntu-18.04" 17 | chmod +x z3-$VER-x64-ubuntu-18.04/bin/z3 18 | mv "z3-$VER-x64-ubuntu-18.04/bin/z3" "$HOME/.local/bin/z3" 19 | echo "Downloaded z3 $VER" 20 | } 21 | 22 | fetch_z3_macos() { 23 | VER="$1" 24 | wget "https://github.com/Z3Prover/z3/releases/download/z3-$VER/z3-$VER-x64-osx-10.15.7.zip" 25 | unzip "z3-$VER-x64-osx-10.15.7" 26 | chmod +x z3-$VER-x64-osx-10.15.7/bin/z3 27 | mv "z3-$VER-x64-osx-10.15.7/bin/z3" "$HOME/.local/bin/z3" 28 | echo "Downloaded z3 $VER" 29 | } 30 | 31 | if [ "$HOST_OS" = "Linux" ]; then 32 | travis_retry fetch_z3_linux "4.8.10" 33 | else 34 | travis_retry fetch_z3_macos "4.8.10" 35 | fi 36 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: "Build" 2 | on: 3 | pull_request: 4 | push: 5 | 6 | concurrency: 7 | group: ${{ github.workflow }}-${{ github.ref }} 8 | cancel-in-progress: true 9 | 10 | jobs: 11 | build: 12 | strategy: 13 | matrix: 14 | os: [ ubuntu-latest, macos-latest ] 15 | # we need this to map platform names as used by github to 16 | # the attribute names defined in release.nix 17 | include: 18 | - os: ubuntu-latest 19 | os_attr: linux 20 | - os: macos-latest 21 | os_attr: darwin 22 | fail-fast: false 23 | runs-on: ${{ matrix.os }} 24 | steps: 25 | - uses: actions/checkout@v3 26 | # v22 27 | - uses: cachix/install-nix-action@v22 28 | with: 29 | # https://discourse.nixos.org/t/understanding-binutils-darwin-wrapper-nix-support-bad-substitution/11475/2 30 | nix_path: nixpkgs=channel:nixos-unstable 31 | # v12 32 | - uses: cachix/cachix-action@v12 33 | with: 34 | name: dapp 35 | signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' 36 | - name: run dapp tests 37 | run: nix-shell --pure src/dapp-tests/shell.nix --command 'make ci --directory src/dapp-tests' 38 | - name: run hevm symbolic tests 39 | run: nix-build -j 1 -A hevm-tests 40 | - run: nix-collect-garbage 41 | - run: nix-build release.nix -A dapphub.${{ matrix.os_attr }}.stable 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | result 2 | result-* 3 | dist-newstyle/ 4 | src/ethsign/ethsign 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dapphub/dapptools/a782a9dfcbf87756170c975c30e83339a99194b5/.gitmodules -------------------------------------------------------------------------------- /ARCHITECTURE.md: -------------------------------------------------------------------------------- 1 | # Build System 2 | 3 | All tools in this directory are built with `nix`, a declarative package manager 4 | which gives a secure and predictable bundling of dependencies. 5 | 6 | They are defined as attributes in the `./overlay.nix` file, 7 | which in turn imports the `default.nix` file of each tool. 8 | 9 | The dependencies of each tool is set as `buildInputs` in the `default.nix` file. 10 | 11 | # dapp & seth 12 | 13 | `dapp` and `seth` are similarly structured as a collection of short scripts, mostly written in bash. 14 | The main entrypoint for any invocation of `seth` or `dapp` is a dispatch script, 15 | `./src/seth/libexec/seth/seth` and `./src/dapp/libexec/dapp/dapp` respectively, which parses any 16 | flags given, setting their values to the appropriate environment variable, and dispatches to the 17 | appropriate subcommand. 18 | 19 | # hevm 20 | 21 | The core evm semnatics in hevm can be found in `EVM.hs`. EVM state is contained in the `VM` record, 22 | and the `exec1` function executes a single opcode inside the monad `type EVM a = State VM a`. 23 | 24 | The core semantics are pure, and should information from the outside world be required to continue 25 | execution (rpc queries, smt queires, user input), execution will halt, and the `result` field of the 26 | VM will be an instance of `VMFailure (Query _)`. 27 | 28 | Multiple steps of EVM execution are orchestrated via interpreters for a meta language. Programs in 29 | the meta language are called Steppers. The instructions in the meta language can be found in 30 | `Stepper.hs`. 31 | 32 | There are many different interpreters with different 33 | features, e.g. a concrete interpreter, a symbolic interpreter, an interpreter that collects coverage 34 | information, a debug interpreter that can accept user input. Interpreters can handle Queries in 35 | different ways, for example in the symbolic inerpreter, both sides of a branch point will be 36 | explored, while in the symbolic debug interpreter, user input will be requested to determine which 37 | side of the branch point will be taken. 38 | 39 | Interpreters are parameterized by a `Fetcher` that can handle rpc and smt queries, and can be 40 | instantiated with fetchers that could have different fetching strategies (e.g. caching). 41 | 42 | Interpreters execute Steppers and use their Fetcher to handle any Queries that need to be resolved. 43 | 44 | This architecure is very modular and pluggable, and allows the core semantics to be shared between 45 | different interpreters, as well as the reuse of steppers between different interpreters, making it 46 | easy to e.g. replay a failed test in the debug interpreter, or to share the same test execution 47 | strategy between concrete and symbolic interpreters. 48 | 49 | ```mermaid 50 | graph LR 51 | subgraph meta-language 52 | A[Stepper] 53 | end 54 | subgraph interpreters 55 | A --> B[Concrete] 56 | A --> C[Symbolic] 57 | A --> D[Coverage] 58 | A --> E[Debug] 59 | end 60 | subgraph fetchers 61 | F[Fetch.hs] 62 | B --> F 63 | C --> F 64 | D --> F 65 | E --> F 66 | end 67 | subgraph EVM Semantics 68 | G[EVM.hs] 69 | B --> G 70 | C --> G 71 | D --> G 72 | E --> G 73 | end 74 | ``` 75 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | { system ? builtins.currentSystem , ... }: 2 | 3 | let 4 | rev = "aa576357673d609e618d87db43210e49d4bb1789"; 5 | nixpkgs = builtins.fetchTarball { 6 | name = "nixpkgs-release-21.05"; 7 | url = "https://github.com/nixos/nixpkgs/tarball/${rev}"; 8 | sha256 = "1868s3mp0lwg1jpxsgmgijzddr90bjkncf6k6zhdjqihf0i1n2np"; 9 | }; 10 | in 11 | # Now return the Nixpkgs configured to use our overlay. 12 | import nixpkgs { 13 | inherit system; 14 | 15 | overlays = [(import ./overlay.nix)]; 16 | } 17 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1622820998, 6 | "narHash": "sha256-1wobInAwYtngN9M4ZqdcIOXWvoyvPt2vDI9TcOvQyKA=", 7 | "owner": "NixOS", 8 | "repo": "nixpkgs", 9 | "rev": "aa576357673d609e618d87db43210e49d4bb1789", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "NixOS", 14 | "repo": "nixpkgs", 15 | "rev": "aa576357673d609e618d87db43210e49d4bb1789", 16 | "type": "github" 17 | } 18 | }, 19 | "root": { 20 | "inputs": { 21 | "nixpkgs": "nixpkgs" 22 | } 23 | } 24 | }, 25 | "root": "root", 26 | "version": 7 27 | } 28 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "dapptools"; 3 | 4 | inputs = { 5 | # same as in default.nix 6 | nixpkgs.url = "github:NixOS/nixpkgs/aa576357673d609e618d87db43210e49d4bb1789"; 7 | }; 8 | 9 | nixConfig = { 10 | # required to build hevm 11 | allow-import-from-derivation = true; 12 | extra-substituters = [ "https://dapp.cachix.org" ]; 13 | extra-trusted-public-keys = [ "dapp.cachix.org-1:9GJt9Ja8IQwR7YW/aF0QvCa6OmjGmsKoZIist0dG+Rs=" ]; 14 | }; 15 | 16 | outputs = { self, nixpkgs }: 17 | let 18 | supportedSystems = [ 19 | "x86_64-darwin" 20 | "x86_64-linux" 21 | ]; 22 | 23 | forAllSystems = nixpkgs.lib.genAttrs supportedSystems; 24 | nixpkgsFor = forAllSystems (system: import nixpkgs { 25 | inherit system; 26 | overlays = [ (import ./overlay.nix) ]; 27 | }); 28 | in 29 | { 30 | packages = 31 | forAllSystems (system: 32 | let pkgs = nixpkgsFor.${system}; in 33 | { 34 | inherit (pkgs) dapp ethsign hevm seth; 35 | 36 | } // pkgs.solc-static-versions); 37 | 38 | apps = 39 | forAllSystems (system: 40 | nixpkgs.lib.genAttrs [ "dapp" "ethsign" "hevm" "seth" ] (name: { 41 | type = "app"; 42 | program = "${self.packages.${system}.${name}}/bin/${name}"; 43 | })); 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /haskell.nix: -------------------------------------------------------------------------------- 1 | # This file was extracted from overlay.nix in order to provide access 2 | # to our Haskell package extensions from other overlays, bypassing the 3 | # rest of our overlay. This was necessary for rather obscure reasons. 4 | 5 | { pkgs, lib, wrapped ? true, shared ? false }: 6 | 7 | let 8 | stdenv = pkgs.stdenv; 9 | 10 | in self-hs: super-hs: 11 | let 12 | dontCheck = x: y: 13 | pkgs.haskell.lib.dontCheck 14 | (self-hs.callCabal2nix x y {}); 15 | 16 | in { 17 | restless-git = dontCheck "restless-git" (./src/restless-git); 18 | 19 | hevm = pkgs.haskell.lib.dontHaddock (( 20 | self-hs.callCabal2nix "hevm" (./src/hevm) { 21 | # Haskell libs with the same names as C libs... 22 | # Depend on the C libs, not the Haskell libs. 23 | # These are system deps, not Cabal deps. 24 | inherit (pkgs) secp256k1; 25 | } 26 | ).overrideAttrs (attrs: { 27 | postInstall = 28 | if wrapped 29 | then 30 | '' 31 | wrapProgram $out/bin/hevm --prefix PATH \ 32 | : "${lib.makeBinPath (with pkgs; [bash coreutils git solc])}" 33 | '' 34 | else ""; 35 | 36 | enableSeparateDataOutput = true; 37 | buildInputs = attrs.buildInputs ++ [pkgs.solc] ++ (if wrapped then [] else [pkgs.z3 pkgs.cvc4]); 38 | nativeBuildInputs = attrs.nativeBuildInputs ++ [pkgs.makeWrapper]; 39 | configureFlags = attrs.configureFlags ++ [ 40 | "--ghc-option=-O2" 41 | ] ++ 42 | (if stdenv.isDarwin then [] else 43 | if shared then [] else [ 44 | "--enable-executable-static" 45 | "--extra-lib-dirs=${pkgs.gmp.override { withStatic = true; }}/lib" 46 | "--extra-lib-dirs=${pkgs.glibc.static}/lib" 47 | "--extra-lib-dirs=${pkgs.libff.override { enableStatic = true; }}/lib" 48 | "--extra-lib-dirs=${pkgs.ncurses.override {enableStatic = true; }}/lib" 49 | "--extra-lib-dirs=${pkgs.zlib.static}/lib" 50 | "--extra-lib-dirs=${pkgs.libffi.overrideAttrs (old: { dontDisableStatic = true; })}/lib" 51 | ]); 52 | })); 53 | } 54 | -------------------------------------------------------------------------------- /nix/LICENSE: -------------------------------------------------------------------------------- 1 | This license ONLY applies to source code of the `overlay` directory, 2 | and not to any of the upstream `nixpkgs` or any of the packages built 3 | by these build specifications. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /nix/build-dapp-package.nix: -------------------------------------------------------------------------------- 1 | { pkgs }: 2 | 3 | let 4 | remappings = xs: 5 | builtins.foldl' pkgs.lib.mergeAttrs {} 6 | (builtins.map 7 | (x: { 8 | "${x.name}/" = "${x}/dapp/${x.name}/src/"; 9 | } // x.remappings) 10 | xs); 11 | libPaths = xs: 12 | builtins.foldl' pkgs.lib.mergeAttrs {} 13 | (builtins.map 14 | (x: { 15 | "${x.name}" = "${x}/dapp/${x.name}/src"; 16 | } // x.libPaths) 17 | xs); 18 | in 19 | { 20 | name 21 | , src 22 | , dapp ? pkgs.dapp 23 | , deps ? [] 24 | , solc ? "${pkgs.solc}/bin/solc" 25 | , shouldFail ? false 26 | , dappFlags ? "" 27 | , doCheck ? true 28 | , ... }@args: 29 | pkgs.stdenv.mkDerivation ( rec { 30 | inherit doCheck; 31 | 32 | buildInputs = [ pkgs.jq dapp ]; 33 | passthru = { 34 | remappings = remappings deps; 35 | libPaths = libPaths deps; 36 | }; 37 | 38 | REMAPPINGS = pkgs.lib.concatStringsSep "\n" 39 | (pkgs.lib.mapAttrsToList 40 | (k: v: k + "=" + v) 41 | passthru.remappings); 42 | 43 | LIBSCRIPT = 44 | pkgs.lib.mapAttrsToList 45 | (k: v: '' 46 | ln -s ${v} lib/${k} 47 | '') 48 | passthru.libPaths; 49 | buildPhase = '' 50 | mkdir -p out 51 | export DAPP_SOLC=${solc} 52 | export DAPP_REMAPPINGS="$REMAPPINGS" 53 | export DAPP_SRC=$src 54 | export DAPP_OUT=out 55 | export DAPP_LINK_TEST_LIBRARIES=1 56 | mkdir -p lib 57 | source <(echo "$LIBSCRIPT") 58 | dapp build 59 | ''; 60 | 61 | checkPhase = let 62 | cmd = "DAPP_SKIP_BUILD=1 dapp test ${dappFlags}"; 63 | in 64 | if shouldFail 65 | then "${cmd} && exit 1 || echo 0" 66 | else cmd; 67 | 68 | installPhase = '' 69 | mkdir -p $out/dapp/$name 70 | cp -r $src $out/dapp/$name/src 71 | cp -r lib $out/dapp/$name/lib 72 | cp -r out $out/dapp/$name/out 73 | ''; 74 | } // args) 75 | -------------------------------------------------------------------------------- /nix/dapptools-src.nix: -------------------------------------------------------------------------------- 1 | { stdenv }: 2 | 3 | stdenv.mkDerivation { 4 | name = "dapptools-src"; 5 | src = ../.; 6 | 7 | phases = [ "unpackPhase" "installPhase" ]; 8 | 9 | installPhase = '' 10 | cp -R . $out 11 | ''; 12 | } 13 | -------------------------------------------------------------------------------- /nix/geth.nix: -------------------------------------------------------------------------------- 1 | { lib, stdenv, buildGoModule, fetchFromGitHub, libobjc ? null, IOKit ? null }: 2 | 3 | let 4 | # A list of binaries to put into separate outputs 5 | bins = [ 6 | "geth" 7 | "clef" 8 | ]; 9 | 10 | in buildGoModule rec { 11 | pname = "go-ethereum"; 12 | version = "1.10.6"; 13 | 14 | src = fetchFromGitHub { 15 | owner = "ethereum"; 16 | repo = pname; 17 | rev = "v${version}"; 18 | sha256 = "sha256-4lapkoxSKdXlD6rmUxnlSKrfH+DeV6/wV05CqJjuzjA="; 19 | }; 20 | 21 | runVend = true; 22 | vendorSha256 = "sha256-5qi01y0SIEI0WRYu2I2RN94QFS8rrlioFvnRqqp6wtk="; 23 | 24 | doCheck = false; 25 | 26 | outputs = [ "out" ] ++ bins; 27 | 28 | # Move binaries to separate outputs and symlink them back to $out 29 | postInstall = lib.concatStringsSep "\n" ( 30 | builtins.map (bin: "mkdir -p \$${bin}/bin && mv $out/bin/${bin} \$${bin}/bin/ && ln -s \$${bin}/bin/${bin} $out/bin/") bins 31 | ); 32 | 33 | subPackages = [ 34 | "cmd/abidump" 35 | "cmd/abigen" 36 | "cmd/bootnode" 37 | "cmd/checkpoint-admin" 38 | "cmd/clef" 39 | "cmd/devp2p" 40 | "cmd/ethkey" 41 | "cmd/evm" 42 | "cmd/faucet" 43 | "cmd/geth" 44 | "cmd/p2psim" 45 | "cmd/puppeth" 46 | "cmd/rlpdump" 47 | "cmd/utils" 48 | ]; 49 | 50 | # Fix for usb-related segmentation faults on darwin 51 | propagatedBuildInputs = 52 | lib.optionals stdenv.isDarwin [ libobjc IOKit ]; 53 | 54 | meta = with lib; { 55 | homepage = "https://geth.ethereum.org/"; 56 | description = "Official golang implementation of the Ethereum protocol"; 57 | license = with licenses; [ lgpl3Plus gpl3Plus ]; 58 | maintainers = with maintainers; [ adisbladis lionello xrelkd RaghavSood ]; 59 | }; 60 | } 61 | -------------------------------------------------------------------------------- /nix/hevm-tests/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs }: 2 | let 3 | solc = "${pkgs.solc-static-versions.solc_0_8_6}/bin/solc-0.8.6"; 4 | solidity = pkgs.fetchFromGitHub { 5 | owner = "ethereum"; 6 | repo = "solidity"; 7 | rev = "b8d736ae0c506b1b3cf5d2456af67e8dc2c0ca8e"; # v0.6.7 8 | sha256 = "1zqfcfgy70hmckxb3l59rabdpzj7gf1vzg6kkw4xz0c6lzy7mrpz"; 9 | }; 10 | runWithSolver = file : solver : (import file) { inherit pkgs solc solidity solver; }; 11 | in 12 | pkgs.recurseIntoAttrs { 13 | yulEquivalence-z3 = runWithSolver ./yul-equivalence.nix "z3"; 14 | yulEquivalence-cvc4 = runWithSolver ./yul-equivalence.nix "cvc4"; 15 | 16 | # z3 takes 3hrs to run these tests on a fast machine, and even then ~180 timeout 17 | #smtChecker-z3 = runWithSolver ./smt-checker.nix "z3"; 18 | smtChecker-cvc4 = runWithSolver ./smt-checker.nix "cvc4"; 19 | } 20 | -------------------------------------------------------------------------------- /nix/libff.nix: -------------------------------------------------------------------------------- 1 | { lib, stdenv, fetchFromGitHub, cmake, boost, gmp, openssl, pkg-config, enableStatic ? false }: 2 | 3 | stdenv.mkDerivation rec { 4 | pname = "libff"; 5 | version = "1.0.0"; 6 | 7 | src = fetchFromGitHub { 8 | owner = "scipr-lab"; 9 | repo = "libff"; 10 | rev = "v${version}"; 11 | sha256 = "0dczi829497vqlmn6n4fgi89bc2h9f13gx30av5z2h6ikik7crgn"; 12 | fetchSubmodules = true; 13 | }; 14 | 15 | cmakeFlags = [ "-DWITH_PROCPS=Off" ]; 16 | 17 | # CMake is hardcoded to always build static library which causes linker 18 | # failure for Haskell applications depending on haskellPackages.hevm on macOS. 19 | postPatch = if (!enableStatic) then '' 20 | substituteInPlace libff/CMakeLists.txt --replace "STATIC" "SHARED" 21 | '' else ""; 22 | 23 | nativeBuildInputs = [ cmake pkg-config ]; 24 | buildInputs = [ boost gmp openssl ]; 25 | 26 | meta = with lib; { 27 | description = "C++ library for Finite Fields and Elliptic Curves"; 28 | changelog = "https://github.com/scipr-lab/libff/blob/develop/CHANGELOG.md"; 29 | homepage = "https://github.com/scipr-lab/libff"; 30 | license = licenses.mit; 31 | platforms = platforms.unix; 32 | maintainers = with maintainers; [ arturcygan ]; 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /nix/make-solc-static.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### helper script for constructing the solc-static nix attrs 3 | 4 | curl https://binaries.soliditylang.org/macosx-amd64/list.json > macos.json 5 | curl https://binaries.soliditylang.org/linux-amd64/list.json > linux.json 6 | 7 | # extract some fields from the json and replace solc_x.y.z with solc_x_y_z 8 | get_info() { 9 | < $1 jq -r '.builds[] 10 | | "solc_\(.version) = { version = \"\(.version)\"; path = \"\(.path)\";" 11 | | sub("solc_(?[0-9]+).(?[0-9]+).(?[0-9]+)"; "solc_\(.x)_\(.y)_\(.z)")' 12 | } 13 | 14 | # the actual binary urls 15 | linux_urls="$(< linux.json jq -r '.builds[] | "https://binaries.soliditylang.org/linux-amd64/\(.path)"')" 16 | macos_urls="$(< macos.json jq -r '.builds[] | "https://binaries.soliditylang.org/macosx-amd64/\(.path)"')" 17 | 18 | get_hashes() { 19 | for url in $1; do 20 | sha256=$(nix-prefetch-url --type sha256 "$url") 21 | echo "sha256 = "'"'${sha256}'"'"; };" 22 | done 23 | } 24 | 25 | linux="$(paste -d' ' <(get_info linux.json) <(get_hashes "$linux_urls"))" 26 | macos="$(paste -d' ' <(get_info macos.json) <(get_hashes "$macos_urls"))" 27 | # now paste this into solc-static-versions.nix 28 | echo "x86_64-linux = {" 29 | echo "$linux" 30 | echo "};" 31 | echo "x86_64-darwin = {" 32 | echo "$macos" 33 | echo "};" 34 | -------------------------------------------------------------------------------- /nix/solc-static.nix: -------------------------------------------------------------------------------- 1 | {path, version, sha256}: 2 | 3 | {stdenv, fetchurl, lib, z3, makeWrapper, autoPatchelfHook}: 4 | let 5 | # solc uses dlopen to look for z3 at runtime, and expects to find a library 6 | # called libz3.so.4.8 exactly. The z3.lib provided by nixpkgs only has a 7 | # libz3.so, so we have to hack around it with this derivation that gives us a 8 | # copy of libz3.so with the name that solc expects. 9 | # At some point in the future we're going to need some logic to provide 10 | # different versions of z3 to different versions of solc, but for now we just 11 | # give z3-4.8 to every version of solc 12 | split = lib.strings.splitString "." z3.version; 13 | z3-exact = stdenv.mkDerivation { 14 | pname = z3.pname; 15 | version = z3.version; 16 | src = null; 17 | phases = [ "installPhase" ]; 18 | installPhase = '' 19 | mkdir -p $out/lib 20 | cp ${z3.lib}/lib/libz3.so $out/lib/libz3.so.${builtins.elemAt split 0}.${builtins.elemAt split 1} 21 | ''; 22 | }; 23 | in 24 | 25 | stdenv.mkDerivation rec { 26 | pname = "solc-static"; 27 | inherit version; 28 | 29 | platform = 30 | if lib.strings.hasPrefix "solc-linux-amd64" "${path}" 31 | then "linux-amd64" 32 | else "macosx-amd64"; 33 | 34 | dontUnpack = true; 35 | dontConfigure = true; 36 | dontBuild = true; 37 | 38 | solc = fetchurl { 39 | url = "https://binaries.soliditylang.org/${platform}/${path}"; 40 | sha256 = "${sha256}"; 41 | }; 42 | 43 | nativeBuildInputs = [ autoPatchelfHook makeWrapper ]; 44 | 45 | postFixup = if (platform == "linux-amd64") then '' 46 | wrapProgram $out/bin/solc-${version} \ 47 | --prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [ z3-exact ]} 48 | '' else ""; 49 | 50 | installPhase = '' 51 | mkdir -p $out/bin 52 | install ${solc} $out/bin/solc-${version} 53 | chmod +x $out/bin/solc-${version} 54 | ''; 55 | } 56 | -------------------------------------------------------------------------------- /nix/solc-updates.md: -------------------------------------------------------------------------------- 1 | # solc updates 2 | 3 | 1. update `dapphub/nixpkgs:master` to `nixos/nixpkgs:master` 4 | 1. create a new branch (`solc-X.Y.Z`) from `dapphub/nixpkgs:master` 5 | 1. in `pkgs/development/compilers/solc/default.nix` 6 | 1. set `version` to `X.Y.Z` 7 | 1. update `rev` and `sha256` based on the output from `nix-prefetch-git git@github.com:ethereum/solidity.git vX.Y.Z` 8 | 1. check the build by running `nix-build -A solc` from the repo root 9 | 1. tweak as needed to get the build passing 10 | 1. install the new version of solc into your local env (`nix-env -f . -iA solc`) and run a few 11 | tests to make sure everything is OK. 12 | 1. commit the changes 13 | 1. create a new branch (`solc-X.Y.Z`) in `dapphub/dapptools` 14 | 1. in `nix/solc-versions.nix` 15 | 1. add a new `solc_X.Y.Z` in the `unreleased` section 16 | 1. update `rev` and `sha256` based on the output from `nix-prefetch-git 17 | git@github.com:dapphub/nixpkgs refs/heads/solc-X.Y.Z` 18 | 1. bump the version number in `dapp---version`, `src/dapp/default.nix` and the changelog 19 | 1. commit the changes 20 | 1. open a pr from `dapphub/dapptools:solc-X.Y.Z` to `dapphub/dapptools:master` 21 | 1. once merged tag the commit with the new version number 22 | 1. open a pr from `dapphub/nixpkgs:solc-X.Y.Z` to `nixos/nixpkgs:master` 23 | 1. once merged make a new PR in `dapphub/dapptools` moving the `solc_X.Y.Z` from the `unreleased` to 24 | the `common` section in `solc-versions.nix` 25 | -------------------------------------------------------------------------------- /nix/solidity-package.nix: -------------------------------------------------------------------------------- 1 | { pkgs }: let 2 | remappings = xs: 3 | builtins.foldl' pkgs.lib.mergeAttrs {} 4 | (builtins.map 5 | (x: { 6 | "${x.name}/" = "${x}/dapp/${x.name}/src/"; 7 | "${x.name}" = "${x}/dapp/${x.name}/src/index.sol"; 8 | } // x.remappings) 9 | xs); 10 | libPaths = xs: 11 | builtins.foldl' pkgs.lib.mergeAttrs {} 12 | (builtins.map 13 | (x: { 14 | "${x.name}" = "${x}/dapp/${x.name}"; 15 | } // x.libPaths) 16 | xs); 17 | in 18 | pkgs.lib.makeOverridable ( 19 | { doCheck ? true 20 | , extract ? true 21 | , deps ? [] 22 | , solc ? pkgs.solc 23 | , hevm ? pkgs.hevm 24 | , solcFlags ? "" 25 | , flatten ? false 26 | , ... 27 | } @ attrs: 28 | pkgs.stdenv.mkDerivation (rec { 29 | inherit doCheck extract; 30 | buildInputs = [ solc pkgs.jq ] 31 | ++ pkgs.lib.optional (flatten || doCheck) hevm; 32 | passthru = { 33 | remappings = remappings deps; 34 | libPaths = libPaths deps; 35 | }; 36 | 37 | REMAPPINGS = 38 | pkgs.lib.mapAttrsToList 39 | (k: v: k + "=" + v) 40 | passthru.remappings; 41 | 42 | LIBSCRIPT = 43 | pkgs.lib.mapAttrsToList 44 | (k: v: '' 45 | ln -s ${v} lib/${k} 46 | '') 47 | passthru.libPaths; 48 | 49 | builder = ./solidity-package.sh; 50 | } // attrs) 51 | ) 52 | -------------------------------------------------------------------------------- /nix/solidity-package.sh: -------------------------------------------------------------------------------- 1 | source $stdenv/setup 2 | unpackPhase 3 | 4 | dir="$out/dapp/$name" 5 | opts=(--combined-json=abi,bin,bin-runtime,srcmap,srcmap-runtime,ast,metadata --overwrite) 6 | 7 | mkdir -p "$dir" 8 | cd "$dir" 9 | 10 | cp -r "$src" src 11 | 12 | mkdir -p lib 13 | source <(echo "$LIBSCRIPT") 14 | 15 | mkdir -p out 16 | mapfile -t files < <(find "$dir/src" -name '*.sol') 17 | json_file="out/dapp.sol.json" 18 | (set -x; solc $REMAPPINGS "${opts[@]}" $solcFlags "${files[@]}" > "$json_file") 19 | 20 | if [[ "$doCheck" == 1 ]]; then 21 | DAPP_OUT=out dapp test 22 | fi 23 | 24 | if [[ $flatten == 1 && ! $x =~ \.t(\.[a-z0-9]+)*\.sol$ ]]; then 25 | flat_file="$DAPP_OUT/$dir/${x##*/}.flat" 26 | (set -x; solc $REMAPPINGS --allow-paths $DAPP_SRC $solcFlags $jsonopts "$x" >"$json_file") 27 | (set -x; hevm flatten --source-file "$x" --json-file "$json_file" >"$flat_file") 28 | x="$flat_file" 29 | fi 30 | 31 | if [ "$extract" == 1 ]; then 32 | mapfile -t contracts < <(<"$json_file" jq '.contracts|keys[]' -r | sort -u -t: -k2 | sort) 33 | data=$(<"$json_file" jq '.contracts' -r) 34 | total=${#contracts[@]} 35 | echo "Extracting build data... [Total: $total]" 36 | for path in "${contracts[@]}"; do 37 | fileName="${path#*:}" 38 | contract=$(echo "$data" | jq '.["'"$path"'"]') 39 | echo "$contract" | jq '.["abi"]' -r > "out/$fileName.abi" 40 | echo "$contract" | jq '.["bin"]' -r > "out/$fileName.bin" 41 | echo "$contract" | jq '.["bin-runtime"]' -r > "out/$fileName.bin-runtime" 42 | echo "$contract" | jq '.["metadata"]' -r > "out/$fileName.metadata" 43 | done 44 | fi 45 | -------------------------------------------------------------------------------- /release.nix: -------------------------------------------------------------------------------- 1 | { ... }: 2 | 3 | let 4 | system = (system: (import ./default.nix { inherit system; })); 5 | linux = system "x86_64-linux"; 6 | darwin = system "x86_64-darwin"; 7 | 8 | ethereum-test-suite = x: x.fetchFromGitHub { 9 | owner = "ethereum"; 10 | repo = "tests"; 11 | rev = "e20d7f39aae1e33394ae6b94590d15083e224fa5"; 12 | sha256 = "1i68k3b8sxawbm65mwph8d5ld9jdjh08c6hln0vygjgwmd0j4n30"; 13 | }; 14 | 15 | # run all General State Tests, skipping performance heavy tests and the ones missing 16 | # postState. 17 | hevmCompliance = x: x.runCommand "hevm-compliance" {} '' 18 | mkdir "$out" 19 | export PATH=${x.pkgs.hevm}/bin:${x.pkgs.jq}/bin:$PATH 20 | ${x.pkgs.hevm}/bin/hevm compliance \ 21 | --tests ${ethereum-test-suite x} \ 22 | --skip "(Create2Recursive|Create1000|recursiveCreateReturn|underflowTest|walletRemoveOwnerRemovePending|Return5000|randomStatetest177|loopExp|loopMul|FirstByte)" \ 23 | --timeout 20 \ 24 | --html > $out/index.html 25 | # Disable obsolete VMTests - gas expectations broken by Istanbul 26 | # ${x.pkgs.hevm}/bin/hevm compliance \ 27 | # --tests ${ethereum-test-suite x} \ 28 | # --group "VM" 29 | ''; 30 | 31 | # These packages should always work and be available in the binary cache. 32 | stable = dist: with dist.pkgs; { 33 | inherit hevm; 34 | inherit dapp; 35 | inherit ethsign; 36 | inherit go-ethereum-unlimited; 37 | inherit go-ethereum; 38 | inherit qrtx-term; 39 | inherit qrtx; 40 | inherit seth; 41 | inherit token; 42 | inherit solc-versions; 43 | 44 | inherit dapp-tests; 45 | inherit hevm-tests; 46 | hevm-compliance = hevmCompliance dist; 47 | }; 48 | 49 | in { 50 | dapphub.linux.stable = stable linux; 51 | dapphub.darwin.stable = stable darwin; 52 | } 53 | -------------------------------------------------------------------------------- /src/dapp-tests/.gitignore: -------------------------------------------------------------------------------- 1 | gethout 2 | hevmout 3 | __pycache__/ 4 | out 5 | -------------------------------------------------------------------------------- /src/dapp-tests/Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | pytest --hypothesis-show-statistics integration/diff-fuzz.py 3 | bash_unit integration/tests.sh 4 | 5 | ci: 6 | pytest --hypothesis-show-statistics integration/diff-fuzz.py 7 | FUZZ_RUNS=10000 TESTNET_SLEEP=90 bash_unit integration/tests.sh 8 | 9 | .PHONY: test 10 | -------------------------------------------------------------------------------- /src/dapp-tests/fail/cheatCodes.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.7; 2 | pragma experimental ABIEncoderV2; 3 | 4 | import "ds-test/test.sol"; 5 | 6 | interface Hevm { 7 | function warp(uint256) external; 8 | function roll(uint256) external; 9 | function load(address,bytes32) external returns (bytes32); 10 | function store(address,bytes32,bytes32) external; 11 | function sign(uint256,bytes32) external returns (uint8,bytes32,bytes32); 12 | function addr(uint256) external returns (address); 13 | function ffi(string[] calldata) external returns (bytes memory); 14 | } 15 | 16 | contract TestFailCheatCodes is DSTest { 17 | Hevm hevm = Hevm(HEVM_ADDRESS); 18 | 19 | function testBadFFI() public { 20 | string[] memory inputs = new string[](2); 21 | inputs[0] = "echo"; 22 | inputs[1] = "acab"; 23 | 24 | // should revert if --ffi hasn't been passed to hevm... 25 | hevm.ffi(inputs); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/dapp-tests/fail/dsProveFail.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.7; 2 | 3 | import "ds-test/test.sol"; 4 | import "ds-token/token.sol"; 5 | import "ds-math/math.sol"; 6 | 7 | contract Withdraw { 8 | receive() external payable {} 9 | 10 | function withdraw(uint password) public { 11 | require(password == 42, "Access denied!"); 12 | payable(msg.sender).transfer(address(this).balance); 13 | } 14 | } 15 | 16 | 17 | contract SolidityTest is DSTest, DSMath { 18 | DSToken token; 19 | Withdraw withdraw; 20 | 21 | function setUp() public { 22 | token = new DSToken("TKN"); 23 | withdraw = new Withdraw(); 24 | } 25 | 26 | function prove_add(uint x, uint y) public { 27 | assertTrue(x + y >= x); 28 | } 29 | 30 | function proveFail_shouldFail(address usr) public { 31 | usr.call(""); 32 | } 33 | 34 | function prove_smtTimeout(uint x, uint y, uint z) public { 35 | if ((x * y / z) * (x / y) / (x * y) == (x * x * x * y * z / x * z * y)) { 36 | assertTrue(false); 37 | } else { 38 | assertTrue(true); 39 | } 40 | } 41 | 42 | function prove_multi(uint x) public { 43 | if (x == 3) { 44 | assertTrue(false); 45 | } else if (x == 9) { 46 | assertTrue(false); 47 | } else if (x == 1023423194871904872390487213) { 48 | assertTrue(false); 49 | } else { 50 | assertTrue(true); 51 | } 52 | } 53 | 54 | function prove_mul(uint136 x, uint128 y) public { 55 | mul(x,y); 56 | } 57 | 58 | function prove_distributivity(uint120 x, uint120 y, uint120 z) public { 59 | assertEq(add(x, mul(y, z)), mul(add(x, y), add(x, z))); 60 | } 61 | 62 | function prove_transfer(uint supply, address usr, uint amt) public { 63 | token.mint(supply); 64 | 65 | uint prebal = token.balanceOf(usr); 66 | token.transfer(usr, amt); 67 | uint postbal = token.balanceOf(usr); 68 | 69 | uint expected = usr == address(this) 70 | ? 0 // self transfer is a noop 71 | : amt; // otherwise `amt` has been transfered to `usr` 72 | assertEq(expected, postbal - prebal); 73 | } 74 | 75 | function proveFail_withdraw(uint guess) public { 76 | payable(address(withdraw)).transfer(1 ether); 77 | uint preBalance = address(this).balance; 78 | withdraw.withdraw(guess); 79 | uint postBalance = address(this).balance; 80 | assertEq(preBalance + 1 ether, postBalance); 81 | } 82 | 83 | // allow sending eth to the test contract 84 | receive() external payable {} 85 | } 86 | 87 | -------------------------------------------------------------------------------- /src/dapp-tests/fail/invariantFail.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.7; 2 | 3 | import "ds-test/test.sol"; 4 | 5 | contract Testdapp { 6 | uint public x; 7 | function f() public { 8 | x++; 9 | } 10 | function g(uint y) public { 11 | if (y % 2 == 0) x*=2; 12 | } 13 | } 14 | 15 | 16 | contract TestdappTest is DSTest { 17 | Testdapp testdapp; 18 | 19 | function setUp() public { 20 | testdapp = new Testdapp(); 21 | } 22 | 23 | function invariantFirst() public { 24 | assertLt(testdapp.x(), 100); 25 | } 26 | } 27 | 28 | contract BrokenCoin { 29 | mapping(address=>uint) public balanceOf; 30 | constructor(uint amount) public { 31 | balanceOf[msg.sender] = amount; 32 | } 33 | 34 | function transfer(address to, uint amount) public { 35 | uint senderBal = balanceOf[msg.sender]; 36 | uint toBal = balanceOf[to]; 37 | require(senderBal >= amount); 38 | senderBal += amount; 39 | toBal -= amount; 40 | balanceOf[msg.sender] = senderBal; 41 | balanceOf[to] = toBal; 42 | } 43 | } 44 | 45 | contract InvariantTest is DSTest { 46 | BrokenCoin token; 47 | User user; 48 | address[] targetContracts_; 49 | 50 | function targetContracts() public returns (address[] memory) { 51 | return targetContracts_; 52 | } 53 | function setUp() public { 54 | token = new BrokenCoin(100 ether); 55 | user = new User(token); 56 | token.transfer(address(user), 100 ether); 57 | targetContracts_.push(address(user)); 58 | } 59 | 60 | function invariantTestUserBal() public { 61 | assertLe(token.balanceOf(address(user)), 100 ether); 62 | } 63 | } 64 | 65 | contract InvariantCount is DSTest { 66 | BrokenAtStart count; 67 | address[] targetContracts_; 68 | 69 | function targetContracts() public returns (address[] memory) { 70 | return targetContracts_; 71 | } 72 | function setUp() public { 73 | count = new BrokenAtStart(); 74 | targetContracts_.push(address(count)); 75 | } 76 | 77 | // this can only fail if we call the invariant method before calling any other method in the target contracts 78 | function invariantCount() public { 79 | assertGt(count.count(), 0); 80 | } 81 | } 82 | 83 | contract BrokenAtStart { 84 | uint public count; 85 | 86 | function inc() public { 87 | count++; 88 | } 89 | } 90 | 91 | contract User { 92 | BrokenCoin token; 93 | constructor(BrokenCoin token_) public { 94 | token = token_; 95 | } 96 | 97 | function doTransfer(address to, uint amount) public { 98 | token.transfer(to, amount); 99 | } 100 | 101 | function doSelfTransfer(uint amount) public { 102 | token.transfer(address(this), amount); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/dapp-tests/genesis.json: -------------------------------------------------------------------------------- 1 | {"alloc":{"0x51A42faFBC93CF0a82fc67c565481Ddeff1aEBFD":{"balance":"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}},"config":{"byzantiumBlock":0,"chainId":99,"clique":{"epoch":3000,"period":0},"constantinopleBlock":0,"eip150Block":0,"eip155Block":0,"eip158Block":0,"eip160Block":0,"homesteadBlock":0,"istanbulBlock":0,"petersburgBlock":0,"berlinBlock":0},"difficulty":"0x1","extraData":"0x313233340000000000000000000000000000000000000000000000000000000051A42faFBC93CF0a82fc67c565481Ddeff1aEBFD0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","gaslimit":"0xffffffffffffffff"} 2 | -------------------------------------------------------------------------------- /src/dapp-tests/integration/contracts/AB.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.8; 2 | 3 | contract A { 4 | uint y; 5 | function set(uint x) public { 6 | y = x; 7 | } 8 | } 9 | 10 | // B some extra weird noops 11 | contract B { 12 | uint z; 13 | function set(uint x) public { 14 | unchecked { z = x + 2 - 2; } 15 | if (z == 4291) { 16 | z = 4291; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/dapp-tests/integration/contracts/factor.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.15; 2 | contract A { 3 | function factor(uint x, uint y) public pure { 4 | require(1 < x && x < 973013 && 1 < y && y < 973013); 5 | assert(x*y != 973013); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/dapp-tests/integration/contracts/stateful.sol: -------------------------------------------------------------------------------- 1 | contract A { 2 | uint x; 3 | 4 | constructor(uint y) public { 5 | x = y; 6 | } 7 | 8 | function off() public { 9 | require(x == 1); 10 | x = 0; 11 | } 12 | 13 | function on() public { 14 | require(x == 0); 15 | x = 1; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/dapp-tests/integration/contracts/token.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract Token { 5 | mapping(address => uint) public balanceOf; 6 | uint public totalSupply; 7 | 8 | constructor(uint supply) { 9 | totalSupply = supply; 10 | balanceOf[msg.sender] = supply; 11 | } 12 | 13 | function transfer(address to, uint256 value) public { 14 | require(to != msg.sender); 15 | balanceOf[msg.sender] -= value; 16 | balanceOf[to] += value; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/dapp-tests/pass/abstract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.7; 2 | 3 | import {DSTest} from "ds-test/test.sol"; 4 | 5 | // should not be run (no code) 6 | abstract contract MyTest is DSTest { 7 | function testAbstract() public { 8 | assertTrue(true); 9 | } 10 | } 11 | 12 | // should run and pass 13 | contract TestMy is MyTest { 14 | function testTrue() public { 15 | assertTrue(true); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/dapp-tests/pass/cheatCodes.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.7; 2 | pragma experimental ABIEncoderV2; 3 | 4 | import "ds-test/test.sol"; 5 | 6 | interface Hevm { 7 | function warp(uint256) external; 8 | function roll(uint256) external; 9 | function load(address,bytes32) external returns (bytes32); 10 | function store(address,bytes32,bytes32) external; 11 | function sign(uint256,bytes32) external returns (uint8,bytes32,bytes32); 12 | function addr(uint256) external returns (address); 13 | function ffi(string[] calldata) external returns (bytes memory); 14 | } 15 | 16 | contract HasStorage { 17 | uint slot0 = 10; 18 | } 19 | 20 | contract CheatCodes is DSTest { 21 | address store = address(new HasStorage()); 22 | Hevm hevm = Hevm(HEVM_ADDRESS); 23 | 24 | function test_warp_concrete(uint128 jump) public { 25 | uint pre = block.timestamp; 26 | hevm.warp(block.timestamp + jump); 27 | assertEq(block.timestamp, pre + jump); 28 | } 29 | 30 | function prove_warp_symbolic(uint128 jump) public { 31 | test_warp_concrete(jump); 32 | } 33 | 34 | function test_roll_concrete(uint64 jump) public { 35 | uint pre = block.number; 36 | hevm.roll(block.number + jump); 37 | assertEq(block.number, pre + jump); 38 | } 39 | 40 | function test_store_load_concrete(uint x) public { 41 | uint ten = uint(hevm.load(store, bytes32(0))); 42 | assertEq(ten, 10); 43 | 44 | hevm.store(store, bytes32(0), bytes32(x)); 45 | uint val = uint(hevm.load(store, bytes32(0))); 46 | assertEq(val, x); 47 | } 48 | 49 | function prove_store_load_symbolic(uint x) public { 50 | test_store_load_concrete(x); 51 | } 52 | 53 | function test_sign_addr_digest(uint sk, bytes32 digest) public { 54 | if (sk == 0) return; // invalid key 55 | 56 | (uint8 v, bytes32 r, bytes32 s) = hevm.sign(sk, digest); 57 | address expected = hevm.addr(sk); 58 | address actual = ecrecover(digest, v, r, s); 59 | 60 | assertEq(actual, expected); 61 | } 62 | 63 | function test_sign_addr_message(uint sk, bytes memory message) public { 64 | test_sign_addr_digest(sk, keccak256(message)); 65 | } 66 | 67 | function testFail_sign_addr(uint sk, bytes32 digest) public { 68 | uint badKey = sk + 1; 69 | 70 | (uint8 v, bytes32 r, bytes32 s) = hevm.sign(badKey, digest); 71 | address expected = hevm.addr(sk); 72 | address actual = ecrecover(digest, v, r, s); 73 | 74 | assertEq(actual, expected); 75 | } 76 | 77 | function testFail_addr_zero_sk() public { 78 | hevm.addr(0); 79 | } 80 | 81 | function testFFI() public { 82 | string[] memory inputs = new string[](3); 83 | inputs[0] = "echo"; 84 | inputs[1] = "-n"; 85 | inputs[2] = "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000046163616200000000000000000000000000000000000000000000000000000000"; 86 | 87 | (string memory output) = abi.decode(hevm.ffi(inputs), (string)); 88 | assertEq(output, "acab"); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/dapp-tests/pass/dsProvePass.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.7; 2 | 3 | import "ds-test/test.sol"; 4 | import "ds-token/token.sol"; 5 | import "ds-math/math.sol"; 6 | 7 | contract ConstructorArg { 8 | address immutable public a; 9 | constructor(address _a) public { 10 | a = _a; 11 | } 12 | } 13 | 14 | contract SolidityTest is DSTest, DSMath { 15 | DSToken token; 16 | 17 | function setUp() public { 18 | token = new DSToken("TKN"); 19 | } 20 | 21 | function prove_add(uint x, uint y) public { 22 | if (x + y < x) return; // no overflow 23 | assertTrue(x + y >= x); 24 | } 25 | 26 | function prove_balance(address usr, uint amt) public { 27 | assertEq(0, token.balanceOf(usr)); 28 | token.mint(usr, amt); 29 | assertEq(amt, token.balanceOf(usr)); 30 | } 31 | 32 | function prove_supply(uint supply) public { 33 | token.mint(supply); 34 | uint actual = token.totalSupply(); 35 | assertEq(supply, actual); 36 | } 37 | 38 | function prove_constructorArgs(address b) public { 39 | ConstructorArg c = new ConstructorArg(b); 40 | assertEq(b, c.a()); 41 | } 42 | 43 | function proveFail_revertSmoke() public { 44 | require(false); 45 | } 46 | 47 | function proveFail_assertSmoke() public { 48 | assertTrue(false); 49 | } 50 | 51 | function prove_transfer(uint supply, address usr, uint amt) public { 52 | if (amt > supply) return; // no underflow 53 | 54 | token.mint(supply); 55 | 56 | uint prebal = token.balanceOf(usr); 57 | token.transfer(usr, amt); 58 | uint postbal = token.balanceOf(usr); 59 | 60 | uint expected = usr == address(this) 61 | ? 0 // self transfer is a noop 62 | : amt; // otherwise `amt` has been transfered to `usr` 63 | assertEq(expected, postbal - prebal); 64 | } 65 | 66 | function prove_burn(uint supply, uint amt) public { 67 | if (amt > supply) return; // no undeflow 68 | 69 | token.mint(supply); 70 | token.burn(amt); 71 | 72 | assertEq(supply - amt, token.totalSupply()); 73 | } 74 | 75 | function prove_loop(uint n) public { 76 | uint counter = 0; 77 | for (uint i = 0; i < n; i++) { 78 | counter++; 79 | } 80 | assertTrue(counter < 100); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/dapp-tests/pass/invariants.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.7; 2 | 3 | import "ds-test/test.sol"; 4 | import "ds-token/token.sol"; 5 | import "ds-math/math.sol"; 6 | 7 | contract InvariantTest is DSTest { 8 | DSToken token; 9 | User user; 10 | address[] targetContracts_; 11 | 12 | function targetContracts() public returns (address[] memory) { 13 | return targetContracts_; 14 | } 15 | 16 | function setUp() public { 17 | token = new DSToken("TKN"); 18 | token.mint(100 ether); 19 | user = new User(token); 20 | token.transfer(address(user), 100 ether); 21 | targetContracts_.push(address(user)); 22 | } 23 | 24 | function invariantTestThisBal() public { 25 | assertLe(token.balanceOf(address(user)), 100 ether); 26 | } 27 | function invariantTotSupply() public { 28 | assertEq(token.totalSupply(), 100 ether); 29 | } 30 | } 31 | 32 | contract User { 33 | DSToken token; 34 | constructor(DSToken token_) public { 35 | token = token_; 36 | } 37 | 38 | function doTransfer(address to, uint amount) public { 39 | token.transfer(to, amount); 40 | } 41 | 42 | function doSelfTransfer(uint amount) public { 43 | token.transfer(address(this), amount); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/dapp-tests/pass/libraries.sol: -------------------------------------------------------------------------------- 1 | import "ds-test/test.sol"; 2 | 3 | library A { 4 | function f(uint128 x) public returns (uint256) { 5 | return uint(x) * 2; 6 | } 7 | } 8 | 9 | contract B is DSTest { 10 | using A for uint128; 11 | function test_f(uint128 x) public { 12 | assertEq(uint(x) * 2, x.f()); 13 | } 14 | 15 | function testFail_f() public { 16 | assertEq(1, uint128(1).f()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/dapp-tests/shell.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs ? import ../.. {} 3 | }: 4 | 5 | with pkgs; 6 | let 7 | my-python-packages = python-packages: with python-packages; [ 8 | hypothesis 9 | pytest 10 | # other python packages you want 11 | ]; 12 | python-with-pkgs = python3.withPackages my-python-packages; 13 | in 14 | 15 | mkShell { 16 | name = "dapp-tests"; 17 | buildInputs = [ 18 | bashInteractive 19 | bash_unit 20 | bc 21 | cacert 22 | coreutils 23 | curl 24 | dapp 25 | gnumake 26 | go-ethereum 27 | hevm 28 | jq 29 | killall 30 | procps 31 | python-with-pkgs 32 | seth 33 | solc 34 | util-linux 35 | which 36 | ]; 37 | LANG="en_US.UTF-8"; 38 | } 39 | -------------------------------------------------------------------------------- /src/dapp/.gitignore: -------------------------------------------------------------------------------- 1 | /docs/_build 2 | -------------------------------------------------------------------------------- /src/dapp/.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dapphub/dapptools/a782a9dfcbf87756170c975c30e83339a99194b5/src/dapp/.gitmodules -------------------------------------------------------------------------------- /src/dapp/.travis-test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | ETHRUN=https://github.com/dapphub/ethrun/releases/download/v0.2.4/ethrun-v0.2.4-linux.tar.gz 4 | ( cd /tmp; curl -LO "$ETHRUN"; tar xf *.tar.gz; sudo mv ethrun /usr/local/bin/ ) 5 | 6 | nix-channel --add https://nix.dapphub.com/pkgs/dapphub 7 | nix-channel --update 8 | nix-env -i ShellCheck solc seth nodejs hevm git 9 | 10 | make test 11 | sudo make link 12 | dapp selftest 13 | -------------------------------------------------------------------------------- /src/dapp/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | language: nix 3 | script: ./.travis-test 4 | -------------------------------------------------------------------------------- /src/dapp/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:7.10.0 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y sudo git wget curl make bc && \ 5 | git clone https://github.com/dapphub/seth && \ 6 | git clone https://github.com/dapphub/dapp && \ 7 | make link -C seth && \ 8 | make link -C dapp && \ 9 | wget https://github.com/dapphub/ethrun/releases/download/v0.2.4/ethrun-v0.2.4-linux.tar.gz && \ 10 | tar xfz ethrun-v0.2.4-linux.tar.gz && \ 11 | mv ethrun /usr/local/bin/ethrun && \ 12 | chmod +x /usr/local/bin/ethrun && \ 13 | rm -rf ethrun-v0.2.4-linux.tar.gz && \ 14 | wget https://github.com/ethereum/solidity/releases/download/v0.4.23/solc-static-linux && \ 15 | mv solc-static-linux /usr/local/bin/solc && \ 16 | chmod +x /usr/local/bin/solc && \ 17 | echo "node ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers 18 | 19 | USER node 20 | ENV USER node 21 | 22 | WORKDIR /home/node 23 | 24 | RUN curl https://nixos.org/nix/install | bash 25 | RUN /nix/var/nix/profiles/default/bin/nix-env -i jshon 26 | 27 | VOLUME /src 28 | WORKDIR /src 29 | CMD [ "dapp", "test"] 30 | -------------------------------------------------------------------------------- /src/dapp/Makefile: -------------------------------------------------------------------------------- 1 | default: test 2 | 3 | SHELL = bash 4 | dirs = {bin,libexec,resources} 5 | prefix ?= /usr/local 6 | 7 | dirs:; mkdir -p $(prefix)/$(dirs) 8 | files = $(shell ls -d $(dirs)/*) 9 | install:; cp -r -n $(dirs) $(prefix) 10 | link: uninstall dirs; for x in $(files); do \ 11 | ln -s `pwd`/$$x $(prefix)/$$x; done 12 | uninstall:; rm -rf $(addprefix $(prefix)/,$(files)) 13 | 14 | test: 15 | set -e; \ 16 | for x in libexec/*/*; do [[ -f $$x ]] && files+=($$x); done; \ 17 | ! grep '^#!/bin/sh' "$${files[@]}"; \ 18 | grep '^#!/usr/bin/env bash' "$${files[@]}" | \ 19 | cut -d: -f1 | xargs shellcheck --exclude=2001 20 | 21 | .PHONY: default dirs install link uninstall test 22 | -------------------------------------------------------------------------------- /src/dapp/bin/dapp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | PATH=${0%/*/*}/libexec/dapp:$PATH exec dapp "$@" 3 | -------------------------------------------------------------------------------- /src/dapp/default.nix: -------------------------------------------------------------------------------- 1 | { lib, stdenv, fetchFromGitHub, makeWrapper, glibcLocales 2 | , coreutils, git, gnused, gnumake, hevm, jshon, jq, nix 3 | , nodejs, perl, python3, seth, shellcheck, solc, tre, dapptoolsSrc }: 4 | 5 | stdenv.mkDerivation rec { 6 | name = "dapp-${version}"; 7 | version = "0.35.0"; 8 | src = ./.; 9 | 10 | nativeBuildInputs = [makeWrapper shellcheck coreutils nodejs python3]; 11 | buildPhase = "true"; 12 | doCheck = true; 13 | checkPhase = "make test"; 14 | makeFlags = ["prefix=$(out)"]; 15 | 16 | postInstall = 17 | let 18 | path = lib.makeBinPath [ 19 | coreutils git gnused gnumake hevm jshon jq nix nodejs perl seth solc tre python3 20 | ]; 21 | in 22 | '' 23 | wrapProgram "$out/bin/dapp" \ 24 | --prefix PATH : ${path} \ 25 | --set DAPPTOOLS ${dapptoolsSrc} \ 26 | ${lib.optionalString (glibcLocales != null) '' 27 | --set LOCALE_ARCHIVE ${glibcLocales}/lib/locale/locale-archive 28 | ''} 29 | ''; 30 | 31 | # the patching of python shebangs is needed by the python invocations in 32 | # src/dapp-tests/integration/tests.sh. 33 | # that's also the reason why nodejs is added to nativeBuildInputs 34 | postFixup = '' 35 | patchShebangs $out/libexec/dapp 36 | ''; 37 | 38 | 39 | meta = { 40 | description = "Simple tool for creating Ethereum-based dapps"; 41 | homepage = https://github.com/dapphub/dapptools/src/dapp/; 42 | maintainers = [lib.maintainers.dbrock]; 43 | license = lib.licenses.gpl3; 44 | inherit version; 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp---find-libraries: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | # Find (heuristically) all the libraries defined in the source 5 | # hierarchy and print them like ``src/Foo.sol:FooLib'' (appropriate 6 | # for `solc --libraries'). 7 | # 8 | # We don't have a "proper" way to find the libraries yet, so we use 9 | # some simple grep/sed magic. If your Solidity source files are weird 10 | # then this might give you trouble. 11 | # 12 | # Instead of making this more smart, I think we could build linking 13 | # into Hevm. It can more accurately determine which libraries are 14 | # needed (via looking at the bytecode and the ASTs). 15 | 16 | mapfile -t sources < <(find "${DAPP_SRC?}" "$DAPP_LIB" -name '*.sol') 17 | grep -EH '^library\s+\w+' "${sources[@]}" \ 18 | | sed -E 's/:library[[:blank:]]+([_[:alnum:]]+)[[:blank:]]+(\{|is).*/:\1/' \ 19 | | sort | while read -r line; do 20 | echo "$line"; 21 | done 22 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp---find-test-methods: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | let path = process.argv[2] 3 | let abi = JSON.parse(require("fs").readFileSync(path)) 4 | if (abi.filter(x => x.name == "IS_TEST").length > 0) { 5 | abi.filter(x => (x.name || "").match(/^test/)).forEach(method => { 6 | console.log(method.name) 7 | }) 8 | } 9 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp---hevm-opts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | caller=$1; shift 3 | 4 | fail () { 5 | cmd=${caller#*-} 6 | echo >&2 "${caller##*/}: error: $1" && echo >&2 7 | dapp help "$cmd" >&2 8 | exit 1 9 | } 10 | 11 | opts=() 12 | [[ "$DAPP_TEST_FFI" ]] && opts+=(--ffi) 13 | [[ "$DAPP_TEST_SMTDEBUG" ]] && opts+=(--smtdebug) 14 | [[ "$DAPP_TEST_COVERAGE" ]] && opts+=(--coverage) 15 | [[ "$DAPP_TEST_DEPTH" ]] && opts+=(--depth "$DAPP_TEST_DEPTH") 16 | [[ "$DAPP_TEST_CACHE" ]] && opts+=(--cache "$DAPP_TEST_CACHE") 17 | [[ "$DAPP_TEST_MATCH" ]] && opts+=(--match "$DAPP_TEST_MATCH") 18 | [[ "$DAPP_TEST_SOLVER" ]] && opts+=(--solver "$DAPP_TEST_SOLVER") 19 | [[ "$DAPP_TEST_REPLAY" ]] && opts+=(--replay "$DAPP_TEST_REPLAY") 20 | [[ "$DAPP_TEST_VERBOSITY" ]] && opts+=(--verbose "$DAPP_TEST_VERBOSITY") 21 | [[ "$DAPP_TEST_COV_MATCH" ]] && opts+=(--cov-match "$DAPP_TEST_COV_MATCH") 22 | [[ "$DAPP_TEST_FUZZ_RUNS" ]] && opts+=(--fuzz-runs "$DAPP_TEST_FUZZ_RUNS") 23 | [[ "$DAPP_TEST_SMTTIMEOUT" ]] && opts+=(--smttimeout "$DAPP_TEST_SMTTIMEOUT") 24 | [[ "$DAPP_TEST_MAX_ITERATIONS" ]] && opts+=(--max-iterations "$DAPP_TEST_MAX_ITERATIONS") 25 | 26 | 27 | 28 | if [[ "$HEVM_RPC" == "yes" ]]; then 29 | number=${DAPP_TEST_NUMBER:-latest} 30 | echo >&2 "${caller##*/}: rpc block: $number" 31 | b=$(seth block "$number") 32 | n=$(seth --field number <<< "$b") && export DAPP_TEST_NUMBER=$n 33 | t=$(seth --field timestamp <<< "$b") && export DAPP_TEST_TIMESTAMP=$t 34 | opts+=(--rpc "$ETH_RPC_URL") 35 | fi 36 | 37 | echo "${opts[@]}" 38 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp---make-cache: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | [[ "$1" ]] && state="$1" || state="$(TMPDIR=. mktemp -d hevm.cache.XXXXX)" 5 | mkdir -p "$state" 6 | # Try to make sure `git commit' definitely succeeds... 7 | export GIT_CONFIG_NOSYSTEM=1 8 | export GIT_AUTHOR_NAME=hevm 9 | export GIT_AUTHOR_EMAIL=hevm@dapphub.com 10 | export GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME 11 | export GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL 12 | gitopts=(-q --no-verify --no-gpg-sign --allow-empty -m "dapp test") 13 | ( cd "$state" ; git init -q && git add . && git commit "${gitopts[@]}" ) 14 | echo "$state" 15 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp---make-library-state: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | if [ "$DAPP_VERBOSE" ]; then set -x; fi 4 | 5 | # First, to support library linking, we build up a "state directory" 6 | # that contains the initial deployed contracts. This way we can 7 | # directly put code at arbitrary addresses, which is how we fake the 8 | # deployed libraries. 9 | # 10 | # Funnily enough, Hevm loads state directories not from the file 11 | # system directly, but via Git. Because these state directories are 12 | # ephemeral, it adds some complexity to this script: we create a 13 | # one-commit Git repository, run the tests, then delete it. 14 | # 15 | # (The state directory support of Hevm is made to allow persistence. 16 | # That's why we use Git repositories: to get atomic behavior and also 17 | # history tracking.) 18 | 19 | sender=0x00a329c0648769a73afac7f9381e08fb43dbea72 20 | nonce=48576 21 | mapfile -t libraries < <(dapp --find-libraries) 22 | 23 | state=$(TMPDIR=. mktemp -d hevm.libs.XXXXX) 24 | state="$(dapp --make-cache "$state")" 25 | 26 | for lib in "${libraries[@]}"; do 27 | address=$(dapp address "$sender" "$nonce") 28 | # shellcheck disable=SC2140 29 | bin=$(jq -r ."contracts".\""${lib/:*/}"\"."${lib/*:/}".evm.bytecode.object "$DAPP_JSON") 30 | if [[ "$bin" != null ]] ; then 31 | echo >&2 "dapp: Predeploying test library $lib at $address" 32 | mkdir -p "$state/$address" 33 | # make sure git commits succeed 34 | export GIT_CONFIG_NOSYSTEM=1 35 | export GIT_AUTHOR_NAME=hevm 36 | export GIT_AUTHOR_EMAIL=hevm@dapphub.com 37 | export GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME 38 | export GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL 39 | 40 | hevm exec --address "$address" --code "$bin" --create > /dev/null --gas 1000000000 --state "$state" 41 | fi 42 | ((nonce++)) 43 | done 44 | 45 | echo "$state" 46 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp---nix-run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Usage: dapp --nix-run PKG COMMAND... 3 | # Example: 4 | # $ dapp --nix-run go-ethereum geth --version 5 | # 6 | # Runs a command with the binaries from a named Nix package in PATH. 7 | 8 | set -e 9 | 10 | have() { command -v "$1" >/dev/null; } 11 | { have nix; } || { 12 | echo >&2 "${0##*/}: error: The Nix package manager is required." 13 | echo >&2 "${0##*/}: error: See https://dapp.tools for installation instructions." 14 | exit 1 15 | } 16 | 17 | expr="$1"; shift 18 | 19 | nix run "(with import $DAPPTOOLS {}; $expr)" -c "$@" 20 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp---parse-deps: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp---parse-deps -- parse arguments into (unparsed, name, url) tuples. 3 | ### Usage: dapp --parse-deps ... 4 | set -e 5 | 6 | for x; do 7 | # matches strings like foo/bar 8 | if [[ ${x:?} =~ ^[^/]+/([^/]+)$ ]]; then 9 | echo "$x" "${BASH_REMATCH[1]}" "https://github.com/$x" 10 | # matches strings like foo:bar or /foo/bar 11 | elif [[ $x =~ .*[:/](.*) ]]; then 12 | name=${BASH_REMATCH[1]} 13 | echo "$x" "${name:?}" "$x" 14 | else 15 | echo "$x" "$x" "https://github.com/dapphub/$x" 16 | fi 17 | done 18 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp---sanity: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | git status --porcelain | grep -qv '^??' || exit 0 3 | exec >&2 4 | git status 5 | echo "${1##*/}: please commit or stash your changes first" 6 | exit 1 7 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp---use: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | function usage() { 5 | echo >&2 "Usage: dapp --use ..." 6 | echo >&2 "Example:" 7 | echo >&2 8 | echo >&2 " $ dapp --use solc:0.4.11 test" 9 | echo >&2 10 | exit 1 11 | } 12 | 13 | [[ "$#" -gt 0 ]] || usage 14 | 15 | query() { 16 | nix-env -q --installed --out-path --no-name "$1" 2>/dev/null 17 | } 18 | 19 | shopt -s extglob 20 | case $1 in 21 | # package spec e.g. solc:0.4.12 22 | solc:[0-9].+([0-9.])) 23 | solc="solc-${1#solc:}" 24 | if store_path=$(query "solc-${1#solc:}"); then 25 | bin="$store_path/bin/solc" 26 | elif store_path=$(query "solc-static-${1#solc:}"); then 27 | bin="$store_path/bin/$solc" 28 | else 29 | bin="" 30 | fi 31 | ;; 32 | # some other solc binary name 33 | solc*) 34 | solc="$1" 35 | set +e 36 | bin="$(type -p "$solc")" 37 | ;; 38 | # if there's a '/', interpret as a path 39 | */*) 40 | bin="$1" 41 | ;; 42 | *) 43 | echo >&2 "${0##*/}: unrecognized package spec: $1" 44 | exit 1 45 | esac 46 | shift 47 | 48 | [[ "$#" -gt 0 ]] || usage 49 | 50 | if [[ -z "$bin" ]]; then 51 | echo >&2 "${0##*/}: Could not find ${solc} in your path or nix store." 52 | echo >&2 "Temporarily installing ${solc}..." 53 | echo >&2 "Tip: run \`nix-env -f https://github.com/dapphub/dapptools/archive/master.tar.gz -iA solc-static-versions.${solc//[-.]/_}\` for a lasting installation of this version." 54 | dapp --nix-run "dapp.override {solc = pkgs.runCommand \"solc\" { } \"mkdir -p \$out/bin; ln -s \${solc-static-versions.${solc//[-.]/_}}/bin/${solc} \$out/bin/solc\";}" dapp "$@" 55 | 56 | exit 0 57 | else 58 | set -e 59 | SOLCBIN="$(realpath -e "${bin}")" 60 | fi 61 | 62 | DAPP_SOLC="$SOLCBIN" dapp "$@" 63 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp---version: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo dapp 0.35.0 3 | # use a custom path is DAPP_SOLC is set 4 | SOLC=${DAPP_SOLC:-solc} 5 | $SOLC --version 6 | echo "hevm $(hevm version)" 7 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-address: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-address -- determine address of newly generated contract 3 | ### Usage: dapp address 4 | set -e 5 | [[ $# -ne 2 ]] && echo "Usage: dapp address " >&2 && exit 1 6 | 7 | sender=$1 8 | nonce=$(seth --to-hex "$2") 9 | 10 | # manually create the rlp encoding of [sender,nonce], with length prefix 11 | # `192+len(sender)+len(nonce):len(sender):sender:128+len(nonce):nonce` 12 | if [[ $nonce -eq 0x00 ]]; then 13 | # encoding of scalar 0 is special and requires the length prefix 14 | rlp="0xd694${sender##0x}80" 15 | elif [[ $nonce -lt 0x80 ]]; then 16 | nonce=$(printf "0x%02x" "$nonce") 17 | # no length prefix if nonce < 128 18 | rlp="0xd694${sender##0x}${nonce##0x}" 19 | elif [[ $nonce -lt 0x100 ]]; then 20 | # even padding for hex 21 | nonce=$(printf "0x%02x" "$nonce") 22 | rlp="0xd794${sender##0x}81${nonce##0x}" 23 | elif [[ $nonce -lt 0x10000 ]]; then 24 | # even padding for hex 25 | nonce=$(printf "0x%04x" "$nonce") 26 | rlp="0xd894${sender##0x}82${nonce##0x}" 27 | else 28 | echo "dapp-address: only supports nonce < 65536" >&2 29 | exit 1 30 | fi 31 | 32 | raw_address=$(seth keccak "$rlp" | cut -b 27-66) 33 | seth --to-checksum-address "$raw_address" 34 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-build -- compile the source code 3 | ### Usage: dapp build [--extract] 4 | ### 5 | ### --extract: After building, write the .abi, .bin and .bin-runtime. Implies `--legacy` 6 | ### files from the solc json into $DAPP_OUT. Beware of contract 7 | ### name collisions. This is provided for compatibility with older 8 | ### workflows. 9 | ### --optimize: activate the solidity optimizer. 10 | ### --via-ir change compilation pipeline to go through the Yul intermediate representation 11 | ### --legacy: Compile using the `--combined-json` flag. Some options are 12 | ### missing from this format. This is provided for compatibility with older 13 | ### workflows. 14 | set -e 15 | 16 | info() { 17 | while [[ $# -gt 0 ]]; do 18 | opt=$1; shift 19 | case $opt in 20 | -*) 21 | FLAGS=$opt; 22 | ;; 23 | *) 24 | ARGS=$opt; 25 | ;; 26 | esac 27 | done 28 | echo >&2 "$FLAGS" "${0##*/}: $ARGS" 29 | } 30 | 31 | colorize() { 32 | awk '{ 33 | gsub("Warning:", "\033[1;33m&\033[0m"); 34 | gsub(".*Error:", "\033[1;31m&\033[0m"); 35 | print }' 36 | } 37 | 38 | cd "$DAPP_ROOT" 39 | 40 | # use a custom path if DAPP_SOLC is set 41 | export SOLC=${DAPP_SOLC:-solc} 42 | 43 | if [ "$DAPP_LINK_TEST_LIBRARIES" = 1 ]; then 44 | sender=0x00a329c0648769a73afac7f9381e08fb43dbea72 45 | nonce=48576 46 | mapfile -t libraries < <(dapp --find-libraries) 47 | 48 | if [[ ${#libraries[@]} -gt 0 ]]; then 49 | 50 | info "building with linked libraries" 51 | for lib in "${libraries[@]}"; do 52 | address=$(dapp address "$sender" "$nonce") 53 | links+=" $lib:$address" 54 | ((nonce++)) 55 | done 56 | fi 57 | else 58 | (set -x; dapp clean) 59 | fi 60 | 61 | export -f info 62 | export DAPP_LIBRARIES=${DAPP_LIBRARIES-"$links"} 63 | 64 | mkdir -p "$DAPP_OUT" 65 | 66 | if [[ -z "$DAPP_BUILD_LEGACY" && -z "$DAPP_BUILD_EXTRACT" ]]; then 67 | if [[ "$SOLC_FLAGS" ]]; then 68 | info "warning: SOLC_FLAGS are only recognized using '--legacy'" 69 | info "consider using --optimize or a custom standard-json instead." 70 | fi 71 | if [[ "$DAPP_STANDARD_JSON" ]]; then 72 | "$SOLC" --allow-paths . --standard-json < "$DAPP_STANDARD_JSON" > "$DAPP_JSON" 73 | else 74 | dapp mk-standard-json | "$SOLC" --standard-json --allow-paths . > "$DAPP_JSON" 75 | fi 76 | 77 | # pipe errors to stderr 78 | jq -r 'if .errors then .errors | map(."formattedMessage") | @sh else empty end' "$DAPP_JSON" \ 79 | | sed -e "s/' //g" -e "s/'//g" -e 's/\\\(.\)\\/\1 /g' | colorize 1>&2 80 | # if sources is empty, the compilation failed 81 | [[ $(jq -r '.sources' "$DAPP_JSON") = "null" || $(jq -r '.sources' "$DAPP_JSON") = {} ]] && exit 1 || exit 0 82 | 83 | else 84 | info "warning: legacy builds are deprecated and might not work with other dapp commands" 85 | dapp build-legacy 86 | fi 87 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-build-legacy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-build-legacy -- compile the source code using --combined-json 3 | ### Usage: dapp build-legacy 4 | 5 | set -e 6 | 7 | IFS=" " read -r -a opts <<<"$SOLC_FLAGS" 8 | json_opts=--combined-json=abi,bin,bin-runtime,srcmap,srcmap-runtime,ast,metadata 9 | 10 | $SOLC --help | grep -q -- --storage-layout && json_opts+=,storage-layout 11 | $SOLC --help | grep -q -- --overwrite && opts+=(--overwrite) 12 | 13 | opts+=(--libraries "$DAPP_LIBRARIES") 14 | 15 | if [[ "$DAPP_REMAPPINGS" ]]; then 16 | while read -r line; do opts+=("$line"); done <<<"$DAPP_REMAPPINGS" 17 | fi 18 | 19 | mapfile -t files < <(find "${DAPP_SRC}" -name '*.sol') 20 | (set -x; $SOLC "${opts[@]}" "${json_opts[@]}" /=/ "${files[@]}" > "${DAPP_JSON}") 21 | 22 | if [ "$DAPP_BUILD_EXTRACT" ]; then 23 | mapfile -t contracts < <(<"$DAPP_JSON" jq '.contracts|keys[]' -r | sort -u -t: -k2 | sort) 24 | data=$(<"$DAPP_JSON" jq '.contracts' -r) 25 | count=1 26 | total=${#contracts[@]} 27 | for path in "${contracts[@]}"; do 28 | info -ne "Extracting build data... [$count/$total]\\r" 29 | ((count++)) 30 | name="${path#*:}" 31 | contract=$(echo "$data" | jq '.[''"'"$path"'"'']') 32 | echo "$contract" | jq '.["abi"]' -r > "$DAPP_OUT/$name.abi" 33 | echo "$contract" | jq '.["bin"]' -r > "$DAPP_OUT/$name.bin" 34 | echo "$contract" | jq '.["bin-runtime"]' -r > "$DAPP_OUT/$name.bin-runtime" 35 | echo "$contract" | jq '.["metadata"]' -r > "$DAPP_OUT/$name.metadata" 36 | done 37 | echo 38 | info "warning: --extract is slow and may have filename collisions. All build data can be found in $DAPP_JSON.\\n" 39 | fi 40 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-check-snapshot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-check-snapshot -- check snapshot is up to date 3 | ### Usage: dapp check-snapshot 4 | set -e 5 | 6 | # Uses the output of dapp test to compare with dapp snapshot 7 | DIFF="$(diff .gas-snapshot <(dapp test --fuzz-runs 0 | grep 'gas:' | cut -d " " -f 2-4))" 8 | 9 | if [ -n "$DIFF" ] 10 | then 11 | echo "$DIFF" 12 | exit 1 13 | fi 14 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-clean: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-clean -- remove compiled source directory 3 | ### Usage: dapp clean 4 | set -e 5 | (set -x; rm -rf "${DAPP_OUT?}") 6 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-clone: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-clone -- clone a github repo 3 | ### Usage: dapp clone 4 | set -e 5 | deps=$(dapp --parse-deps "$@") 6 | while read -r _ name url; do 7 | ssh_url=${url/https:\/\/github.com\//git@github.com:} 8 | (set -x; git clone "$ssh_url" "$name" --recursive) 9 | done <<<"$deps" 10 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-create: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-create -- deploy a compiled contract (--verify on Etherscan) 3 | ### Usage: dapp create or 4 | ### dapp create : 5 | ### Add --verify and export your ETHERSCAN_API_KEY to auto-verify on Etherscan 6 | set -e 7 | 8 | [[ -e "${DAPP_JSON}" ]] || { 9 | echo >&2 "${0##*/}: error: ${DAPP_JSON} file not found. Did you run ``dapp build``?" 10 | exit 1 11 | } 12 | 13 | name=${1?missing contract name} 14 | 15 | mapfile -t contracts < <(<"$DAPP_JSON" jq '.contracts|keys[]' -r) 16 | 17 | name=() 18 | 19 | for path in "${contracts[@]}"; do 20 | if [ -z "${1##*:*}" ]; then 21 | [[ "$path" = "${1/:*/}" ]] && [[ -n "$(jq .contracts.\""$path"\".\""${1#*:}"\"[]? "$DAPP_JSON")" ]] && name+=("$path") 22 | else 23 | [[ -n "$(jq .contracts.\""$path"\".\""$1"\"[]? "$DAPP_JSON")" ]] && name+=("$path") 24 | fi 25 | done 26 | 27 | [[ "${#name[@]}" -eq 0 ]] && { 28 | echo >&2 "${0##*/}: error: $1 not found" 29 | exit 1 30 | } 31 | 32 | [[ "${#name[@]}" -ge 2 ]] && { 33 | echo >&2 "${0##*/}: error: $1 found in multiple files. Use full path:" 34 | printf 'dapp create %s\n' "${name[@]}" 35 | exit 1 36 | } 37 | 38 | contract=$(<"$DAPP_JSON" jq .contracts.\""${name[0]}"\".\""${1#*:}"\") 39 | abi=$(jq .abi -r <<< "$contract") 40 | bin=$(jq .evm.bytecode.object -r <<< "$contract") 41 | type=$(seth --abi-constructor <<< "$abi") 42 | address=$(set -x; seth send --create "$bin" "${type/constructor/${1#*:}}" "${@:2}") 43 | 44 | [[ $DAPP_VERIFY_CONTRACT ]] && { 45 | echo >&2 "Verifying contract at $address" 46 | sleep 5 # give etherscan some time to process the block 47 | dapp verify-contract "$path":"${1#*:}" "$address" "${@:2}" 48 | } 49 | 50 | seth --to-checksum-address "$address" 51 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-debug: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-debug -- run unit tests interactively (hevm) 3 | ### Usage: dapp debug [] 4 | ### 5 | ### Options: 6 | ### --rpc fetch remote state via ETH_RPC_URL 7 | ### --rpc-url= fetch remote state via 8 | ### --rpc-block= block number (latest if not specified) 9 | 10 | set -e 11 | 12 | have() { command -v "$1" >/dev/null; } 13 | have hevm || { 14 | echo >&2 "${0##*/}: error: The hevm executable was not found in \$PATH." 15 | echo >&2 "${0##*/}: error: See https://dapp.tools for installation instructions." 16 | exit 1 17 | } 18 | 19 | opts=$(dapp --hevm-opts "$0" "$@") 20 | 21 | # Link libraries by default. 22 | export DAPP_LINK_TEST_LIBRARIES=${DAPP_LINK_TEST_LIBRARIES-1} 23 | 24 | cd "$DAPP_ROOT" 25 | ( set -x; dapp build || exit ) 26 | 27 | # Make a state dir for linked libraries if needed. 28 | 29 | if [ "$DAPP_LINK_TEST_LIBRARIES" = 1 ] ; then 30 | state=$(dapp --make-library-state) 31 | opts+=("--state ${state}") 32 | function clean() { rm -rf "$state"; } 33 | trap clean EXIT 34 | fi 35 | 36 | # Make sure we know which JSON file to target. 37 | 38 | shopt -s nullglob 39 | shopt -s globstar 40 | jsons=("$DAPP_OUT"/**/*.sol.json) 41 | if [[ "${#jsons[@]}" -gt 1 ]]; then 42 | if [[ "$#" -gt 0 ]]; then 43 | target="$1"; shift 44 | else 45 | echo >&2 "${0##*/}: There are multiple compilation outputs:" 46 | echo >&2 "${0##*/}:" 47 | echo >&2 "${0##*/}: ${jsons[*]}" 48 | echo >&2 "${0##*/}:" 49 | echo >&2 "${0##*/}: Choose one like this:" 50 | echo >&2 "${0##*/}: $ dapp debug ${jsons[0]}" 51 | echo >&2 "${0##*/}:" 52 | exit 1 53 | fi 54 | elif [[ "${#jsons[@]}" -eq 1 ]]; then 55 | target="${jsons[0]}" 56 | elif [[ "${#jsons[@]}" -eq 0 ]]; then 57 | echo >&2 "${0##*/}: error: No compilation outputs; nothing to debug." 58 | fi 59 | 60 | # shellcheck disable=SC2068 61 | (set -x; hevm dapp-test --debug --dapp-root="$DAPP_ROOT" --json-file="$target" ${opts[@]}) 62 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-help: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-help -- print help about dapp or one of its subcommands 3 | ### Usage: dapp help [] 4 | ### or: dapp --help 5 | 6 | BUGS=https://github.com/dapphub/dapptools/issues 7 | 8 | name=dapp 9 | file=${0%-*}${1+-$1} 10 | header=$(perl -ne 'print "$2\n" if /^(\S)\1\1(?: (.*))?/' "$file") 11 | 12 | if ! [[ $header ]]; then 13 | sed "s/^/${0##*/}: /" "$file" 14 | elif [[ $(wc -l <<<"$header") = 1 ]]; then 15 | echo "$header" 16 | else 17 | sed "1{/^$name\\S* -- /d;}" <<<"$header" 18 | fi 19 | 20 | [[ $1 ]] && exit 21 | 22 | for file in "${0%/*}"/"$name"-*; do 23 | if [[ -L $file ]]; then 24 | continue 25 | elif [[ $file = */$name---* ]]; then 26 | special_commands+=("$file") 27 | else 28 | normal_commands+=("$file") 29 | fi 30 | done 31 | 32 | list-commands() { 33 | cat "$@" | 34 | perl -ne 'print "$2 $3\n" if /^(\S)\1\1 '"$name"'-(\S+) -- (.*)/' | 35 | while read -r name label; do 36 | printf " %-14s %s\\n" "$name" "$label" 37 | done | LANG=C sort 38 | } 39 | 40 | cat <<. 41 | 42 | Special commands: 43 | 44 | $(list-commands "${special_commands[@]}") 45 | 46 | Commands: 47 | 48 | $(list-commands "${normal_commands[@]}") 49 | 50 | Report bugs to <$BUGS>. 51 | . 52 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-init: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-init -- bootstrap a new dapp 3 | ### Usage: dapp init 4 | set -e -o noclobber 5 | [[ -e .git ]] && dapp --sanity "$0" 6 | 7 | solc_version=$(solc --version) 8 | solc_version=$(<<<"$solc_version" grep ^Version:) 9 | solc_version=${solc_version#* } 10 | solc_version=${solc_version%%+*} 11 | 12 | create() { [[ -e $1 ]] || { cat >"$1"; (set -x; git add "$1"); }; } 13 | insert() { 14 | touch "$1" 15 | while read -r line; do 16 | grep -qF "$line" "$1" || printf >>"$1" '%s\n' "$line" 17 | done 18 | (set -x; git add "$1") 19 | } 20 | 21 | (set -x; git init) 22 | (set -x; mkdir -p lib src) 23 | 24 | insert .gitignore <<. 25 | /out 26 | . 27 | 28 | create .gitattributes <<. 29 | *.sol linguist-language=Solidity 30 | . 31 | 32 | name=$(basename "$(pwd)") 33 | name=$(<<<"$name" tr '[:upper:]' '[:lower:]') 34 | IFS=" " read -r -a nouns <<<"${name//[^a-z]/ }" 35 | noun=${nouns[$((${#nouns[@]} - 1))]} 36 | type=$(<<<"$name" perl -pe 's/(\w+)/\u$1/g') 37 | type=$(<<<"$type" tr -cd a-zA-Z0-9) 38 | type=${1-$type} 39 | 40 | create Makefile <<. 41 | all :; dapp build 42 | clean :; dapp clean 43 | test :; dapp test 44 | deploy :; dapp create $type 45 | . 46 | 47 | create "src/$type.sol" <<. 48 | // SPDX-License-Identifier: GPL-3.0-or-later 49 | pragma solidity ^${solc_version}; 50 | 51 | contract $type { 52 | } 53 | . 54 | 55 | create "src/$type.t.sol" <<. 56 | // SPDX-License-Identifier: GPL-3.0-or-later 57 | pragma solidity ^${solc_version}; 58 | 59 | import "ds-test/test.sol"; 60 | 61 | import "./$type.sol"; 62 | 63 | contract ${type}Test is DSTest { 64 | $type $noun; 65 | 66 | function setUp() public { 67 | $noun = new $type(); 68 | } 69 | 70 | function testFail_basic_sanity() public { 71 | assertTrue(false); 72 | } 73 | 74 | function test_basic_sanity() public { 75 | assertTrue(true); 76 | } 77 | } 78 | . 79 | 80 | git add -A 81 | (set -x; git commit -m "dapp init $type") 82 | (set -x; dapp install ds-test) 83 | (set -x; DAPP_REMAPPINGS="$(dapp-remappings)" make test) 84 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-install -- install a smart contract library 3 | ### Usage: dapp install 4 | ### may be: 5 | ### - a Dapphub repo (ds-foo) 6 | ### - the URL of a Dapphub repo (https://github.com/dapphub/ds-foo) 7 | ### - a path to a repo in another Github org (org-name/repo-name) 8 | set -e 9 | 10 | dapp --sanity "$0" 11 | deps=$(dapp --parse-deps "$@") 12 | if [[ -z "$deps" ]]; then 13 | dapp help install 14 | exit 15 | fi 16 | 17 | while read -r unparsed name url; do 18 | # get the tag/branch/rev from the repo name if it's specified after the URL with 19 | # an '@' delimiter. 20 | IFS='@' read -ra repo <<< "$url" 21 | url=${repo[0]} 22 | tag=${repo[1]} 23 | # strip the tag from the name 24 | name=${name%@*} 25 | 26 | (set -x; git submodule add --force "$url" "lib/$name") 27 | (set -x; git submodule update --init --recursive "lib/$name") 28 | if [ "$tag" ]; then 29 | # checkout the tag 30 | (set -x; cd "lib/$name" && git checkout --recurse-submodules "$tag" && cd -) 31 | git add "lib/$name" 32 | fi 33 | (set -x; git commit -m "dapp install $unparsed") 34 | done <<<"$deps" 35 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-remappings: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var PROGRAM_NAME = process.argv[1].replace(/.*\//, "") 3 | var pkg_src = {}, pkg_hash = {} 4 | 5 | findRemappings(".") 6 | 7 | Object.keys(pkg_src).sort((a, b) => a.length - b.length).sort( 8 | (a, b) => { 9 | var depth = name => pkg_src[name].split("/").length 10 | return depth(a) - depth(b) 11 | } 12 | ).forEach(name => { 13 | console.log(`${name}/=${pkg_src[name]}/`) 14 | }) 15 | 16 | function findRemappings(prefix) { 17 | ls(`${prefix}/${process.env.DAPP_LIB}`).forEach(name => { 18 | var lib = `${prefix}/${process.env.DAPP_LIB}` 19 | var path = `${lib}/${name}` 20 | var src = `${path}/${process.env.DAPP_SRC}`.replace(/^.\//, "") 21 | 22 | // If the path is a not a directory, return early. 23 | if (!isDir(path)) { 24 | return 25 | } 26 | 27 | // Shortcut when we're ignoring all the Git hash stuff. 28 | if (process.env.DAPP_IGNORE_HASHES) { 29 | pkg_src[name] = src 30 | findRemappings(path) 31 | return 32 | } 33 | 34 | if (ls(path).includes(".git") != true) { 35 | console.error(`${PROGRAM_NAME}: error: ${path} is not a Git repository`) 36 | console.error(`${PROGRAM_NAME}: error: try "dapp update" to initialize submodules`) 37 | process.exit(1) 38 | } 39 | 40 | var hash = run("git", ["-C", src, "rev-parse", "HEAD"]) 41 | 42 | if (pkg_src[name]) { 43 | if (hash != pkg_hash[name]) { 44 | console.error(`${PROGRAM_NAME}: warning: mismatching packages:`) 45 | console.error(`${PROGRAM_NAME}: warning: (1) ${pkg_src[name]}`) 46 | console.error(`${PROGRAM_NAME}: warning: (2) ${src}`) 47 | console.error(`${PROGRAM_NAME}: warning: using ${pkg_src[name]}. You can override this using \`DAPP_REMAPPINGS\``) 48 | } else if (src.length < pkg_src[name].length) { 49 | pkg_src[name] = src 50 | } 51 | } else { 52 | pkg_src[name] = src 53 | pkg_hash[name] = hash 54 | } 55 | 56 | findRemappings(path) 57 | }) 58 | } 59 | 60 | function ls(dir) { 61 | try { 62 | return require("fs").readdirSync(dir).sort() 63 | } catch (error) { 64 | return [] 65 | } 66 | } 67 | 68 | function isDir(path) { 69 | try { 70 | return require("fs").lstatSync(path).isDirectory() 71 | } catch (error) { 72 | return false; 73 | } 74 | } 75 | 76 | function run(cmd, args) { 77 | return require("child_process").execFileSync(cmd, args, { 78 | encoding: "utf-8" 79 | }) 80 | } 81 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-selftest: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex; tmp=$(mktemp -d); cd "$tmp" 3 | 4 | # Try initializing and testing a new dapp 5 | ( mkdir foo; cd foo; dapp init ) 6 | 7 | # Try testing a bunch of dappsys packages 8 | dappsys() { 9 | git clone https://github.com/dapphub/"$1" --recursive 10 | ( cd "$1" && dapp test ) 11 | } 12 | 13 | dappsys ds-auth 14 | # dappsys ds-cache # No test suite 15 | dappsys ds-exec 16 | dappsys ds-guard 17 | dappsys ds-math 18 | # dappsys ds-multisig # Incompatible with Solidity 0.5 19 | dappsys ds-note 20 | dappsys ds-proxy 21 | dappsys ds-roles 22 | dappsys ds-stop 23 | dappsys ds-thing 24 | dappsys ds-token 25 | # dappsys ds-value # No test suite 26 | dappsys ds-vault 27 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-snapshot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-snapshot -- creates a snapshot of each test's gas usage 3 | ### Usage: dapp snapshot 4 | set -e 5 | 6 | # Saves the output of dapp test to .gas-snapshot 7 | dapp test --fuzz-runs 0 | grep 'gas:' | cut -d " " -f 2-4 > .gas-snapshot 8 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-test -- run the test suite 3 | ### Usage: dapp test [] 4 | ### 5 | ### Options: 6 | ### -v, --verbose trace output for failing tests 7 | ### --coverage print coverage data 8 | ### --fuzz-runs number of times to run fuzzing tests 9 | ### --depth number of transactions to sequence per invariant cycle 10 | ### --replay rerun a particular test case 11 | ### -m, --match only run test methods matching regex 12 | ### --cov-match only print coverage for files matching regex 13 | ### 14 | ### RPC options: 15 | ### --rpc fetch remote state via ETH_RPC_URL 16 | ### --rpc-url fetch remote state via 17 | ### --rpc-block block number (latest if not specified) 18 | ### 19 | ### SMT options: 20 | ### --smttimeout timeout passed to the smt solver in ms (default 600000) 21 | ### --solver name of the smt solver to use (either "z3" or "cvc4") 22 | ### --max-iterations number of times we may revisit a particular branching point 23 | set -e 24 | have() { command -v "$1" >/dev/null; } 25 | 26 | cd "$DAPP_ROOT" 27 | 28 | have hevm || { 29 | echo >&2 "${0##*/}: error: \`hevm' not found" 30 | echo >&2 "${0##*/}: error: please install it and try again" 31 | exit 1 32 | } 33 | 34 | export DAPP_LINK_TEST_LIBRARIES=${DAPP_LINK_TEST_LIBRARIES-1} 35 | 36 | if ! [[ $DAPP_SKIP_BUILD ]] ; then 37 | dapp build || exit 38 | fi 39 | 40 | if [ "$DAPP_VERBOSE" ]; then set -x; fi 41 | 42 | opts=$(dapp --hevm-opts "$0" "$@") 43 | 44 | if [ "$DAPP_LINK_TEST_LIBRARIES" = 1 ] ; then 45 | state=$(dapp --make-library-state) 46 | opts+=("--state ${state}") 47 | function clean() { rm -rf "$state"; } 48 | trap clean EXIT 49 | fi 50 | 51 | # make sure git commits succeed 52 | export GIT_CONFIG_NOSYSTEM=1 53 | export GIT_AUTHOR_NAME=hevm 54 | export GIT_AUTHOR_EMAIL=hevm@dapphub.com 55 | export GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME 56 | export GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL 57 | 58 | # shellcheck disable=SC2068 59 | hevm dapp-test --dapp-root="${DAPP_ROOT}" --json-file="${DAPP_JSON}" ${opts[@]} 60 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-test-standalone: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-test-standalone -- test a standalone .sol file with ds-test 3 | ### Usage: dapp test-standalone foo.t.sol 4 | 5 | set -e 6 | 7 | if [ -z "$DAPPSYS_PATH" ]; then 8 | >&2 echo "dapp test-standalone: \$DAPPSYS_PATH must point to dappsys root" 9 | >&2 echo "dapp test-standalone: containing at least ds-test/src/test.sol" 10 | exit 1 11 | fi 12 | 13 | tmp=$(mktemp -d) 14 | mkdir "$tmp"/{src,lib} 15 | cp "$1" "$tmp"/src 16 | cp -r "$DAPPSYS_PATH"/* "$tmp"/lib 17 | cd "$tmp" 18 | DAPP_IGNORE_HASHES=1 dapp test 19 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-testnet: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-testnet -- launch a testnet 3 | ### Usage: dapp testnet [] 4 | dapp --nix-run go-ethereum-unlimited dapp --testnet-launch "$@" 5 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-uninstall: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-uninstall -- remove a smart contract library 3 | ### Usage: dapp uninstall 4 | set -e 5 | dapp --sanity "$0" 6 | for x; do 7 | (set -x; git rm -r "lib/$x") 8 | (set -x; git commit -m "dapp uninstall $x") 9 | done 10 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-update -- fetch all upstream lib changes 3 | ### Usage: dapp update [] 4 | set -e 5 | if [[ $1 ]]; then 6 | for x; do (set -x; git submodule update --init --recursive "lib/$x"); done 7 | else 8 | (set -x; git submodule update --init --recursive) 9 | fi 10 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-upgrade: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### dapp-upgrade -- pull & commit all upstream lib changes 3 | ### Usage: dapp upgrade [] 4 | set -e 5 | dapp --sanity "$0" 6 | 7 | if [[ $1 ]]; then 8 | for x; do 9 | (set -x; git submodule update --init --remote "lib/$x") 10 | if [[ $(git status --porcelain -- lib) ]]; then 11 | (set -x; git add "lib/$x") 12 | (set -x; git commit -m "dapp upgrade $x") 13 | else 14 | echo "${0##*/}: dependency up-to-date: $x" 15 | fi 16 | dapp update "$x" 17 | done 18 | else 19 | for x in lib/*; do libs+=("${x#*/}"); done 20 | dapp upgrade "${libs[@]}" 21 | fi 22 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-verify: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | bin=$DAPP_OUT/${1?missing contract name}.bin-runtime 4 | dbin=$(seth code "${2?missing contract address}" | sed 's/^0x//') 5 | diff -w <(echo "$dbin") "$bin" &> /dev/null && echo true && exit 6 | echo false && exit 1 7 | -------------------------------------------------------------------------------- /src/dapp/libexec/dapp/dapp-version: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | dapp --version -------------------------------------------------------------------------------- /src/ethsign/CHANGELOG: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [0.17.1] - 2021-11-12 8 | 9 | ### Fixed 10 | 11 | Contract creations with Dynamic fee transactions. 12 | 13 | ## [0.17.0] - 2020-02-03 14 | 15 | ### Changed 16 | 17 | - Makes `--keystore` argument to `ethsign import` no longer mandatory, defaulting to 18 | systems paths or to the value of the `ETH_KEYSTORE` environment variable. 19 | - `ethsign import --keystore` was changed to `ethsign import --key-store` for consistency 20 | with other commands. 21 | - [BREAKING] removes Parity / OpenEthereum related default keystores 22 | 23 | ## [0.16.2] - 2020-02-03 24 | 25 | ### Added 26 | 27 | - `ethsign msg --no-prefix` can now sign 712 messages with Ledgers 28 | 29 | ## [0.16.1] - 2020-02-03 30 | 31 | ### Added 32 | 33 | - Lookup both ledger live path and legacy ledger paths by default 34 | 35 | ### Changed 36 | 37 | - updated `nixpkgs` to the `20.09` channel 38 | 39 | ## [0.15.0] - 2020-06-15 40 | 41 | ### Fixed 42 | 43 | - a golang error occurring for `MacOS Catalina` users: [#384](https://github.com/dapphub/dapptools/pull/384) 44 | 45 | [0.15.0]: https://github.com/dapphub/dapptools/tree/ethsign/0.15.0 46 | 47 | ## [0.14.0] - 2020-05-29 48 | 49 | ### Changed 50 | 51 | - add environment flag `ETH_HD_PATH` which can be used to set derivation 52 | path for BIP32 hardware wallets 53 | 54 | [0.14.0]: https://github.com/dapphub/dapptools/tree/ethsign/0.14.0 55 | 56 | ## [0.13.0] - 2019-08-08 57 | 58 | ### Changed 59 | 60 | - add command `import` to create and save an encrypted keyfile in the 61 | keystore based on a private key and a passphrase 62 | 63 | [0.13.0]: https://github.com/dapphub/dapptools/tree/ethsign/0.13.0 64 | 65 | ## [0.12.0] - 2019-03-25 66 | 67 | ### Changed 68 | 69 | - add flag no-prefix to sign a message without the "Begin Ethereum Message" prefix. 70 | 71 | [0.12.0]: https://github.com/dapphub/dapptools/tree/ethsign/0.11.0 72 | 73 | ## [0.11.0] - 2019-02-20 74 | 75 | ### Changed 76 | 77 | - build using latest stable Go in nixpkgs (1.10 at time of commit) 78 | - replace deprecated `ToECDSAPub` function 79 | 80 | [0.11.0]: https://github.com/dapphub/dapptools/tree/ethsign/0.11.0 81 | 82 | -------------------------------------------------------------------------------- /src/ethsign/README.md: -------------------------------------------------------------------------------- 1 | # Ethsign 2 | 3 | Sign Ethereum transactions using a JSON keystore or hardware wallet. 4 | 5 | ## Usage 6 | 7 | ``` 8 | NAME: 9 | ethsign 10 | 11 | USAGE: 12 | ethsign [global options] command [command options] [arguments...] 13 | 14 | VERSION: 15 | 0.16.1 16 | 17 | COMMANDS: 18 | list-accounts, ls List accounts in keystore and USB wallets 19 | transaction, tx Make a signed transaction 20 | message, msg Sign arbitrary data with header prefix 21 | verify Verify signed data by given key 22 | recover Recover Ethereum address from signature 23 | import import hexadecimal private key into keystore 24 | help, h Show a list of commands or help for one command 25 | 26 | ``` 27 | ## Installation 28 | 29 | `ethsign` is distrubuted as part of the [Dapp tools suite](../../README.md). 30 | -------------------------------------------------------------------------------- /src/ethsign/default.nix: -------------------------------------------------------------------------------- 1 | { lib, buildGoModule }: 2 | 3 | buildGoModule rec { 4 | name = "ethsign-${version}"; 5 | version = "0.17.1"; 6 | 7 | src = ./.; 8 | 9 | vendorSha256 = "1zbsq1lyqinyzv5x4p1xgkxsyb7y92fbmf44gyaix34xrag5s27m"; 10 | runVend = true; 11 | 12 | meta = { 13 | homepage = http://github.com/dapphub/dapptools; 14 | description = "Make raw signed Ethereum transactions"; 15 | license = [lib.licenses.agpl3]; 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /src/ethsign/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/dapphub/ethsign 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/OneOfOne/xxhash v1.2.5 // indirect 7 | github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 // indirect 8 | github.com/aws/aws-sdk-go v1.25.48 // indirect 9 | github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa // indirect 10 | github.com/ethereum/go-ethereum v1.10.6 11 | github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 // indirect 12 | github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d // indirect 13 | github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 // indirect 14 | github.com/spaolacci/murmur3 v1.0.1-0.20190317074736-539464a789e9 // indirect 15 | github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect 16 | github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect 17 | github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 // indirect 18 | golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 19 | golang.org/x/mobile v0.0.0-20200801112145-973feb4309de // indirect 20 | gopkg.in/sourcemap.v1 v1.0.5 // indirect 21 | gopkg.in/urfave/cli.v1 v1.20.0 22 | ) 23 | -------------------------------------------------------------------------------- /src/hevm/.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((haskell-mode . ((dante-target . "lib:hevm")))) 2 | -------------------------------------------------------------------------------- /src/hevm/.envrc: -------------------------------------------------------------------------------- 1 | # vim: set ft=sh: 2 | 3 | if has lorri; then 4 | eval "$(lorri direnv)" 5 | else 6 | use nix 7 | fi 8 | -------------------------------------------------------------------------------- /src/hevm/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | dist-newstyle/ 3 | .configured 4 | cabal.project.local* 5 | .stack-work/ 6 | tests/ 7 | -------------------------------------------------------------------------------- /src/hevm/.hlint.yaml: -------------------------------------------------------------------------------- 1 | # HLint configuration file 2 | # https://github.com/ndmitchell/hlint 3 | ########################## 4 | 5 | # This file contains a template configuration file, which is typically 6 | # placed as .hlint.yaml in the root of your project 7 | 8 | 9 | # Warnings currently triggered by your code 10 | - ignore: {name: "Use fewer imports"} 11 | - ignore: {name: "Use if"} 12 | - ignore: {name: "Use newtype instead of data"} 13 | - ignore: {name: "Redundant bracket"} 14 | - ignore: {name: "Reduce duplication"} 15 | - ignore: {name: "Redundant return"} 16 | - ignore: {name: "Use head"} 17 | - ignore: {name: "Use unwords"} 18 | - ignore: {name: "Use <$>"} 19 | - ignore: {name: "Use elem"} 20 | - ignore: {name: "Use infix"} 21 | - ignore: {name: "Use section"} 22 | - ignore: {name: "Move brackets to avoid $"} 23 | - ignore: {name: "Use zipWith"} 24 | - ignore: {name: "Redundant flip"} 25 | - ignore: {name: "Redundant $!"} 26 | -------------------------------------------------------------------------------- /src/hevm/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | services: 3 | - docker 4 | script: 5 | - make hevm-linux-x64 6 | before_deploy: 7 | - tar czf hevm-${TRAVIS_TAG}-linux-x64.tar.gz hevm-linux-x64 8 | deploy: 9 | provider: releases 10 | api_key: 11 | secure: hUZxnwIpX9wzMSuwlgXQ8ybKWfYd6JUhFJBdhJN12cZrH2+fiQX9rmSV1TryGERREo22VNbYi/1tcDEC4nx9xJm50dPcqkw9muL4oMrF0QYU6sAWmnNndHbhZGTTdJ2MBmzz7Gojx3SUNsny8ewtlCBNmiK5MAeNF2jjLZ4ATgR+ABZpkDV1/KhHQGQUuANV3bZ1S/xk/chnAPkoBb8H0HVGCCeL2SKiMt1GWaoNvIEZw7SXqS6wZsSqmu7iqNlu8pnR8K2rVqRXDiBsUYv6QY2P4swHZd3I00FIOI0/962hTORb1bJHyfEGeHV9VGBEBNBMmkW9Al1uD2fO6BqrVMv93Y6FhZ2pySS5DM+9aCZMdCxS01ov5rgEY2B+zv4mDDEXEdfQGkPLVSpGrLkq7t2RAt+unuSpSVcatreqgZvfrPcptDkm7kYk+2aqcR38XJa00uKeEcbNuXaG9Ok/fZ211MKCsd9uZaSr7oBMta0P18sX2RvVY5Kbs9fqPcYgAz2WLqYUM7n3W8AwbRcfFOQ6Ev/PGVJhACcrmCkZI3lc7ojKInQkPm9PdZI8sbrjmHHJ5tQNs5zVACBsRiiWsrT3EFr2Pd6SVb4Hx2Wrq2dq0yGLLhOmPbPt7pBMp3G6/xYMhRZFabKgQ7XeHR5ybrpsvTR+lq/SAvyojauS8Tc= 12 | file: "hevm-${TRAVIS_TAG}-linux-x64.tar.gz" 13 | on: 14 | tags: true 15 | skip_cleanup: true 16 | -------------------------------------------------------------------------------- /src/hevm/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mitchty/alpine-ghc:large 2 | ADD https://github.com/lalyos/docker-upx/releases/download/v3.91/upx /bin/upx 3 | RUN chmod +x /bin/upx 4 | RUN sed -i -e 's/v3\.5/v3.6/g' /etc/apk/repositories 5 | RUN apk add --update bzip2-dev readline-dev readline-static \ 6 | && ln -s /usr/lib/libncursesw.so.6.0 /usr/lib/libncurses.so \ 7 | && ln -s /usr/lib/libncursesw.so.6.0 /usr/lib/libncursesw.so 8 | WORKDIR /src 9 | ADD hevm.cabal /src/ 10 | RUN cabal update && cabal install happy && cabal install --only-dependencies --disable-executable-dynamic 11 | ADD . /src 12 | RUN apk add --update ncurses-static \ 13 | && ln -s /usr/lib/libncursesw.a /usr/lib/libncurses.a \ 14 | && cabal configure --disable-executable-dynamic --ghc-option=-optl-static --ghc-option=-optl-pthread \ 15 | && cabal build \ 16 | && cp dist/build/hevm/hevm /bin/hevm 17 | RUN upx /bin/hevm 18 | -------------------------------------------------------------------------------- /src/hevm/Makefile: -------------------------------------------------------------------------------- 1 | all: build 2 | 3 | .configured: shell.nix 4 | nix-shell --command 'cabal new-configure --enable-tests' --pure 5 | touch .configured 6 | build: .configured 7 | nix-shell --command 'cabal new-build' --pure 8 | repl: .configured 9 | nix-shell --command 'cabal new-repl lib:hevm' --pure 10 | tests: .configured 11 | nix-shell --command 'cabal new-test' --pure 12 | 13 | PORT ?= 8001 14 | BROWSER ?= chromium 15 | hoogle-server:; nix-shell --run 'hoogle server --local -p $(PORT)' 16 | 17 | .PHONY: all build repl 18 | -------------------------------------------------------------------------------- /src/hevm/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /src/hevm/benchmark/benchmark.hs: -------------------------------------------------------------------------------- 1 | main = putStrLn "no benchmark yet" 2 | -------------------------------------------------------------------------------- /src/hevm/ethjet/blake2.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "blake2.h" 3 | 4 | #define ROTR64(x, y) (((x) >> (y)) ^ ((x) << (64 - (y)))) 5 | 6 | #define B2B_G(a, b, c, d, x, y) \ 7 | v[a] = v[a] + v[b] + x; \ 8 | v[d] = ROTR64(v[d] ^ v[a], 32); \ 9 | v[c] = v[c] + v[d]; \ 10 | v[b] = ROTR64(v[b] ^ v[c], 24); \ 11 | v[a] = v[a] + v[b] + y; \ 12 | v[d] = ROTR64(v[d] ^ v[a], 16); \ 13 | v[c] = v[c] + v[d]; \ 14 | v[b] = ROTR64(v[b] ^ v[c], 63); 15 | 16 | static const uint64_t blake2b_iv[8] = { 17 | 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, 18 | 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1, 19 | 0x510E527FADE682D1, 0x9B05688C2B3E6C1F, 20 | 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179 21 | }; 22 | 23 | static const uint8_t sigma[10][16] = { 24 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, 25 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, 26 | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, 27 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, 28 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, 29 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, 30 | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, 31 | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, 32 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, 33 | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 } 34 | }; 35 | 36 | void blake2b_compress(uint64_t *h, uint64_t *m, uint64_t *t, char f, uint32_t rounds) { 37 | uint32_t i; 38 | uint64_t v[16]; 39 | 40 | for (i = 0; i < 8; i++) { 41 | v[i] = h[i]; 42 | v[i+8] = blake2b_iv[i]; 43 | } 44 | 45 | v[12] ^= t[0]; 46 | v[13] ^= t[1]; 47 | 48 | if (f) v[14] = ~v[14]; 49 | 50 | int index; 51 | for (i = 0; i < rounds; i++) { 52 | index = i % 10; 53 | B2B_G( 0, 4, 8, 12, m[sigma[index][ 0]], m[sigma[index][ 1]]); 54 | B2B_G( 1, 5, 9, 13, m[sigma[index][ 2]], m[sigma[index][ 3]]); 55 | B2B_G( 2, 6, 10, 14, m[sigma[index][ 4]], m[sigma[index][ 5]]); 56 | B2B_G( 3, 7, 11, 15, m[sigma[index][ 6]], m[sigma[index][ 7]]); 57 | B2B_G( 0, 5, 10, 15, m[sigma[index][ 8]], m[sigma[index][ 9]]); 58 | B2B_G( 1, 6, 11, 12, m[sigma[index][10]], m[sigma[index][11]]); 59 | B2B_G( 2, 7, 8, 13, m[sigma[index][12]], m[sigma[index][13]]); 60 | B2B_G( 3, 4, 9, 14, m[sigma[index][14]], m[sigma[index][15]]); 61 | } 62 | 63 | for (i = 0; i < 8; ++i) 64 | h[i] ^= v[i] ^ v[i+8]; 65 | } 66 | -------------------------------------------------------------------------------- /src/hevm/ethjet/blake2.h: -------------------------------------------------------------------------------- 1 | #ifndef BLAKE2_H 2 | #define BLAKE2_H 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void 11 | blake2b_compress(uint64_t *h, uint64_t *m, uint64_t *t, char f, uint32_t rounds); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/hevm/ethjet/ethjet-ff.h: -------------------------------------------------------------------------------- 1 | #ifndef ETHJET_FF_H 2 | #define ETHJET_FF_H 3 | 4 | #include 5 | 6 | int 7 | ethjet_ecadd (uint8_t *in, size_t in_size, 8 | uint8_t *out, size_t out_size); 9 | 10 | int 11 | ethjet_ecmul (uint8_t *in, size_t in_size, 12 | uint8_t *out, size_t out_size); 13 | 14 | int 15 | ethjet_ecpairing (uint8_t *in, size_t in_size, 16 | uint8_t *out, size_t out_size); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/hevm/ethjet/ethjet.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBETHJET_H 2 | #define LIBETHJET_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | struct ethjet_context 9 | { 10 | secp256k1_context *ec; 11 | }; 12 | 13 | enum ethjet_operation 14 | { 15 | ETHJET_ECRECOVER = 1, 16 | ETHJET_ECADD = 6, 17 | ETHJET_ECMUL = 7, 18 | ETHJET_ECPAIRING = 8, 19 | ETHJET_BLAKE2 = 9, 20 | ETHJET_EXAMPLE = 0xdeadbeef, 21 | }; 22 | 23 | struct ethjet_context * 24 | ethjet_init (); 25 | 26 | void 27 | ethjet_free (struct ethjet_context *ctx); 28 | 29 | int ethjet (struct ethjet_context *ctx, 30 | enum ethjet_operation op, 31 | uint8_t *in, size_t in_size, 32 | uint8_t *out, size_t out_size); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/hevm/ethjet/tinykeccak.h: -------------------------------------------------------------------------------- 1 | #ifndef KECCAK_H 2 | #define KECCAK_H 3 | 4 | #include 5 | #include 6 | 7 | int sha3_256 (uint8_t *out, size_t out_size, 8 | const uint8_t *in, size_t in_size); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/hevm/hie.yaml: -------------------------------------------------------------------------------- 1 | cradle: 2 | cabal: 3 | - path: "./src" 4 | component: "lib:hevm" 5 | - path: "./hevm-cli" 6 | component: "exe:hevm" 7 | - path: "./test" 8 | component: "test:test" 9 | -------------------------------------------------------------------------------- /src/hevm/run-consensus-tests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | # Invoke with hevm e.g. 5 | # hevm compliance --tests ~/ethereum-tests --group VM --skip quadratic --html 6 | 7 | HEVM=${HEVM:-hevm} 8 | 9 | if [[ "$#" -lt 1 ]]; then 10 | echo >&2 "usage: $(basename "$0") " 11 | exit 1 12 | fi 13 | 14 | tests=$1 15 | html=$2 16 | match=$3 17 | skip=$4 18 | timeout=${5:-10} 19 | 20 | _html() { 21 | cat <<. 22 | 23 | hevm test results 24 | 43 |
44 |

hevm consensus test report

45 |

$(date +%Y-%m-%d)

46 |

$(echo "$npass passed, $nfail failed, $nskip skipped")

47 | (Test suite: VMTests for ConstantinopleFix) 48 |
49 |

Failed tests

50 | 51 | 52 | $(echo $failed) 53 |
54 |

Skipped tests

55 | 56 | 57 | $(echo $skipped) 58 |
59 |

Passed tests

60 | 61 | 62 | $(echo $passed) 63 |
64 | . 65 | } 66 | 67 | { 68 | cd "$tests" 69 | for x in VMTests/*/*; do 70 | if [[ $x =~ .*$match.* ]] && [[ -n $skip && $x =~ .*$skip.* ]]; then 71 | for job in $(<$x jq '.|keys[]' -r); do 72 | echo "$x $job skip" 73 | done 74 | elif [[ $x =~ .*$match.* ]]; then 75 | echo -n "$x " ; "$HEVM" vm-test --file $x --timeout $timeout 2>&1 76 | fi 77 | done 78 | } | { 79 | while read path test outcome; do 80 | echo >&2 "$path $test $outcome" 81 | category=$(dirname "$path") 82 | testcase=$(basename "${path%.json}") 83 | row="$testcase$outcome$category" 84 | row+=$'\n' 85 | case $outcome in 86 | ok) passed+=$row ;; 87 | skip) skipped+=$row ;; 88 | timeout) timouts+=row ;; 89 | *) failed+=$row ;; 90 | esac 91 | done 92 | 93 | sum () { echo -ne "$1" | wc -l | awk '{print $1}'; } 94 | 95 | nfail=$(sum "$failed") 96 | npass=$(sum "$passed") 97 | nskip=$(sum "$skipped") 98 | ntime=$(sum "$timeouts") 99 | 100 | echo >&2 "passed: $npass" 101 | echo >&2 "failed: $nfail" 102 | echo >&2 "timeout: $ntime" 103 | echo >&2 "skipped: $nskip" 104 | 105 | if [[ $html == "True" ]]; then 106 | _html 107 | fi 108 | 109 | [[ $nfail -gt 0 ]] && exit 1 || exit 0 110 | } 111 | -------------------------------------------------------------------------------- /src/hevm/shell.nix: -------------------------------------------------------------------------------- 1 | { dapphub ? import ../.. {} }: 2 | let 3 | inherit (dapphub) pkgs; 4 | 5 | 6 | drv = pkgs.haskellPackages.shellFor { 7 | packages = p: [ 8 | p.hevm 9 | ]; 10 | buildInputs = with pkgs.haskellPackages; [ 11 | cabal-install 12 | haskell-language-server 13 | ]; 14 | withHoogle = true; 15 | }; 16 | in 17 | if pkgs.lib.inNixShell 18 | then drv.overrideAttrs (_: { 19 | LD_LIBRARY_PATH = "${pkgs.secp256k1}/lib:${pkgs.libff}/lib"; 20 | }) 21 | else drv 22 | -------------------------------------------------------------------------------- /src/hevm/src/EVM/Demand.hs: -------------------------------------------------------------------------------- 1 | module EVM.Demand (demand) where 2 | 3 | import Control.DeepSeq (NFData, force) 4 | import Control.Exception.Base (evaluate) 5 | import Control.Monad.IO.Class (MonadIO, liftIO) 6 | 7 | -- | This is an easy way to force full evaluation of a value inside of 8 | -- the IO monad, being essentially just the composition of @evaluate@ 9 | -- and @force@. 10 | demand :: (MonadIO m, NFData a) => a -> m () 11 | demand x = do 12 | _ <- liftIO (evaluate (force x)) 13 | return () 14 | -------------------------------------------------------------------------------- /src/hevm/src/EVM/Facts/Git.hs: -------------------------------------------------------------------------------- 1 | 2 | -- This is a backend for the fact representation that uses a Git 3 | -- repository as the store. 4 | 5 | module EVM.Facts.Git 6 | ( saveFacts 7 | , loadFacts 8 | , RepoAt (..) 9 | ) where 10 | 11 | import EVM.Facts (Fact (..), File (..), Path (..), Data (..), fileToFact, factToFile) 12 | 13 | import Control.Lens 14 | import Data.Set (Set) 15 | import Data.Maybe (catMaybes) 16 | 17 | import qualified Data.Set as Set 18 | import qualified Restless.Git as Git 19 | 20 | newtype RepoAt = RepoAt String 21 | deriving (Eq, Ord, Show) 22 | 23 | -- For modularity reasons, we have our own file data type that is 24 | -- isomorphic with the one in the `restless-git` library. We declare 25 | -- the isomorphism so we can go between them easily. 26 | fileRepr :: Iso' File Git.File 27 | fileRepr = iso f g 28 | where 29 | f :: File -> Git.File 30 | f (File (Path ps p) (Data x)) = 31 | Git.File (Git.Path ps p) x 32 | 33 | g :: Git.File -> File 34 | g (Git.File (Git.Path ps p) x) = 35 | File (Path ps p) (Data x) 36 | 37 | saveFacts :: RepoAt -> Set Fact -> IO () 38 | saveFacts (RepoAt repo) facts = 39 | Git.save repo "hevm execution" 40 | (Set.map (view fileRepr . factToFile) facts) 41 | 42 | prune :: Ord a => Set (Maybe a) -> Set a 43 | prune = Set.fromList . catMaybes . Set.toList 44 | 45 | loadFacts :: RepoAt -> IO (Set Fact) 46 | loadFacts (RepoAt src) = 47 | fmap 48 | (prune . Set.map (fileToFact . view (from fileRepr))) 49 | (Git.load src) 50 | -------------------------------------------------------------------------------- /src/hevm/src/EVM/Precompiled.hs: -------------------------------------------------------------------------------- 1 | {-# Language ForeignFunctionInterface #-} 2 | 3 | module EVM.Precompiled (execute) where 4 | 5 | import Data.ByteString (ByteString) 6 | import qualified Data.ByteString as BS 7 | 8 | import Foreign.C 9 | import Foreign.Ptr 10 | import Foreign.ForeignPtr 11 | 12 | import System.IO.Unsafe 13 | 14 | -- | Opaque representation of the C library's context struct. 15 | data EthjetContext 16 | 17 | foreign import ccall "ethjet_init" 18 | ethjet_init :: IO (Ptr EthjetContext) 19 | foreign import ccall "ðjet_free" 20 | ethjet_free :: FunPtr (Ptr EthjetContext -> IO ()) 21 | foreign import ccall "ethjet" 22 | ethjet 23 | :: Ptr EthjetContext -- initialized context 24 | -> CInt -- operation 25 | -> Ptr CChar -> CInt -- input 26 | -> Ptr CChar -> CInt -- output 27 | -> IO CInt -- 1 if good 28 | 29 | -- Lazy evaluation ensures this context is only initialized once, 30 | -- and `unsafePerformIO` in such situations is a common pattern. 31 | -- 32 | -- We use a "foreign pointer" annotated with a finalizer. 33 | globalContext :: ForeignPtr EthjetContext 34 | {-# NOINLINE globalContext #-} 35 | globalContext = 36 | unsafePerformIO $ 37 | ethjet_init >>= newForeignPtr ethjet_free 38 | 39 | -- | Run a given precompiled contract using the C library. 40 | execute 41 | :: Int -- ^ The number of the precompiled contract 42 | -> ByteString -- ^ The input buffer 43 | -> Int -- ^ The desired output size 44 | -> Maybe ByteString -- ^ Hopefully, the output buffer 45 | execute contract input outputSize = 46 | 47 | -- This code looks messy because of the pointer handling, 48 | -- but it's actually simple. 49 | -- 50 | -- We use `unsafePerformIO` because the contracts are pure. 51 | 52 | unsafePerformIO . BS.useAsCStringLen input $ 53 | \(inputPtr, inputSize) -> do 54 | outputForeignPtr <- mallocForeignPtrBytes outputSize 55 | withForeignPtr outputForeignPtr $ \outputPtr -> do 56 | status <- 57 | withForeignPtr globalContext $ \contextPtr -> 58 | -- Finally, we can invoke the C library. 59 | ethjet contextPtr (fromIntegral contract) 60 | inputPtr (fromIntegral inputSize) 61 | outputPtr (fromIntegral outputSize) 62 | 63 | case status of 64 | 1 -> Just <$> BS.packCStringLen (outputPtr, outputSize) 65 | _ -> pure Nothing 66 | -------------------------------------------------------------------------------- /src/hevm/src/EVM/TTYCenteredList.hs: -------------------------------------------------------------------------------- 1 | module EVM.TTYCenteredList where 2 | 3 | -- Hard fork of brick's List that centers the currently highlighted line. 4 | 5 | import Control.Lens 6 | import Data.Maybe (fromMaybe) 7 | 8 | import Brick.Types 9 | import Brick.Widgets.Core 10 | import Brick.Widgets.List 11 | 12 | import qualified Data.Vector as V 13 | 14 | -- | Turn a list state value into a widget given an item drawing 15 | -- function. 16 | renderList :: (Ord n, Show n) 17 | => (Bool -> e -> Widget n) 18 | -- ^ Rendering function, True for the selected element 19 | -> Bool 20 | -- ^ Whether the list has focus 21 | -> List n e 22 | -- ^ The List to be rendered 23 | -> Widget n 24 | -- ^ rendered widget 25 | renderList drawElem foc l = 26 | withDefAttr listAttr $ 27 | drawListElements foc l drawElem 28 | 29 | drawListElements :: (Ord n, Show n) => Bool -> List n e -> (Bool -> e -> Widget n) -> Widget n 30 | drawListElements foc l drawElem = 31 | Widget Greedy Greedy $ do 32 | c <- getContext 33 | 34 | let es = V.slice start num (l^.listElementsL) 35 | idx = fromMaybe 0 (l^.listSelectedL) 36 | 37 | start = max 0 $ idx - (initialNumPerHeight `div` 2) 38 | num = min (numPerHeight * 2) (V.length (l^.listElementsL) - start) 39 | 40 | -- The number of items to show is the available height divided by 41 | -- the item height... 42 | initialNumPerHeight = (c^.availHeightL) `div` (l^.listItemHeightL) 43 | -- ... but if the available height leaves a remainder of 44 | -- an item height then we need to ensure that we render an 45 | -- extra item to show a partial item at the top or bottom to 46 | -- give the expected result when an item is more than one 47 | -- row high. (Example: 5 rows available with item height 48 | -- of 3 yields two items: one fully rendered, the other 49 | -- rendered with only its top 2 or bottom 2 rows visible, 50 | -- depending on how the viewport state changes.) 51 | numPerHeight = initialNumPerHeight + 52 | if initialNumPerHeight * (l^.listItemHeightL) == c^.availHeightL 53 | then 0 54 | else 1 55 | 56 | -- off = start * (l^.listItemHeightL) 57 | 58 | drawnElements = flip V.imap es $ \i e -> 59 | let isSelected = i == (if start == 0 then idx else div initialNumPerHeight 2) 60 | elemWidget = drawElem isSelected e 61 | selItemAttr = if foc 62 | then withDefAttr listSelectedFocusedAttr 63 | else withDefAttr listSelectedAttr 64 | makeVisible = if isSelected 65 | then visible . selItemAttr 66 | else id 67 | in makeVisible elemWidget 68 | 69 | render $ viewport (l^.listNameL) Vertical $ 70 | -- translateBy (Location (0, off)) $ 71 | vBox $ V.toList drawnElements 72 | -------------------------------------------------------------------------------- /src/hevm/stack.yaml: -------------------------------------------------------------------------------- 1 | resolver: lts-17.14 2 | packages: 3 | - . 4 | extra-deps: 5 | - HSH-2.1.3 6 | - monoidal-containers-0.6.0.1 7 | - restless-git-0.7 8 | - s-cargot-0.1.4.0 9 | - tree-view-0.5 10 | - text-format-0.3.2 11 | - witherable-0.3.5 12 | - base16-bytestring-1.0.1.0@sha256:33b9d57afa334d06485033e930c6b13fc760baf88fd8f715ae2f9a4b46e19a54,2641 13 | - github: dmjio/semver-range 14 | commit: d8d9db892ddb6ae267c9bcbc4f6602668433f12a 15 | - github: leventerkok/sbv # 8.9 16 | commit: b64905e2698c320ac14ffbad53325d33081839fb 17 | flags: {} 18 | extra-package-dbs: [] 19 | image: 20 | container: 21 | name: mbrock/hevm 22 | base: haskell:8.0.1 23 | -------------------------------------------------------------------------------- /src/jays/.gitignore: -------------------------------------------------------------------------------- 1 | /dist 2 | -------------------------------------------------------------------------------- /src/jays/Main.hs: -------------------------------------------------------------------------------- 1 | {-# Language OverloadedStrings #-} 2 | 3 | import Jays (jays) 4 | 5 | import System.Environment (getArgs) 6 | import System.Exit (exitFailure, exitSuccess) 7 | import System.IO (stdout, stderr) 8 | import System.Posix.IO (stdInput) 9 | import System.Posix.Terminal (queryTerminal) 10 | 11 | import Data.Text (pack) 12 | import Data.Monoid ((<>)) 13 | 14 | import qualified Data.ByteString.Lazy.Char8 as BS 15 | 16 | main :: IO () 17 | main = do 18 | isTty <- queryTerminal stdInput 19 | input <- if isTty then pure "" else BS.getContents 20 | args <- getArgs 21 | 22 | if args == ["--version"] 23 | then 24 | -- This is just for compatibility with jshon versioning 25 | putStrLn "20171121" 26 | else 27 | case jays input (map pack args) of 28 | (output, succeeded) -> do 29 | let output' = if BS.null output then "" else output <> "\n" 30 | BS.hPutStr (if succeeded then stdout else stderr) output' 31 | if succeeded then exitSuccess else exitFailure 32 | -------------------------------------------------------------------------------- /src/jays/Makefile: -------------------------------------------------------------------------------- 1 | all: conf; cabal build && cabal test 2 | conf: default.nix shell.nix; \ 3 | nix-shell --command "cabal configure --enable-tests" 4 | default.nix: *.cabal; cabal2nix . > default.nix 5 | 6 | .PHONY: all conf 7 | -------------------------------------------------------------------------------- /src/jays/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /src/jays/jays.cabal: -------------------------------------------------------------------------------- 1 | name: jays 2 | version: 1.20171121 3 | synopsis: Rewrite of jshon 4 | homepage: https://github.com/mbrock/jays 5 | license: GPL-3 6 | license-file: LICENSE 7 | author: Mikael Brockman 8 | maintainer: mikael@brockman.se 9 | build-type: Simple 10 | cabal-version: >=1.10 11 | 12 | library 13 | hs-source-dirs: src 14 | default-language: Haskell2010 15 | ghc-options: -Wall -O2 16 | exposed-modules: Jays 17 | build-depends: 18 | base == 4.*, 19 | bytestring, 20 | containers, 21 | text, 22 | aeson, 23 | aeson-pretty, 24 | unordered-containers, 25 | vector 26 | 27 | executable jays 28 | main-is: Main.hs 29 | hs-source-dirs: . 30 | default-language: Haskell2010 31 | ghc-options: -Wall -threaded -O2 32 | build-depends: 33 | base == 4.*, 34 | jays, 35 | bytestring, 36 | text, 37 | unix 38 | 39 | test-suite test 40 | default-language: Haskell2010 41 | hs-source-dirs: test 42 | ghc-options: -Wall 43 | type: exitcode-stdio-1.0 44 | main-is: Test.hs 45 | build-depends: 46 | base, 47 | jays, 48 | bytestring, 49 | tasty, 50 | tasty-hunit, 51 | HUnit, 52 | aeson, 53 | text 54 | -------------------------------------------------------------------------------- /src/jays/shell.nix: -------------------------------------------------------------------------------- 1 | { nixpkgs ? import {} }: 2 | let 3 | inherit (nixpkgs) pkgs; 4 | haskellPackages = pkgs.haskellPackages.override { 5 | overrides = (self: super: { 6 | ghc = super.ghc // { withPackages = super.ghc.withHoogle; }; 7 | ghcWithPackages = self.ghc.withPackages; 8 | }); 9 | }; 10 | drv = haskellPackages.callPackage (import ./default.nix) {}; 11 | in 12 | if pkgs.lib.inNixShell then drv.env else drv 13 | -------------------------------------------------------------------------------- /src/jays/test/Test.hs: -------------------------------------------------------------------------------- 1 | {-# Language OverloadedStrings #-} 2 | 3 | import Test.Tasty 4 | import Test.Tasty.HUnit 5 | 6 | import Data.ByteString.Lazy (ByteString) 7 | import Data.Text (Text) 8 | 9 | import qualified Data.Text as Text 10 | 11 | import Jays (jays) 12 | 13 | main :: IO () 14 | main = defaultMain tests 15 | 16 | good :: ByteString -> Text -> ByteString -> Assertion 17 | good a b c = jays a (Text.words b) @?= (c, True) 18 | 19 | tests :: TestTree 20 | tests = testGroup "jays" 21 | [ testCase "Create an object" $ do 22 | good "" "-n {}" "{}" 23 | good "" "-n object" "{}" 24 | , testCase "Create a number" $ 25 | good "" "-n 3" "3" 26 | , testCase "Create a float" $ 27 | good "" "-n 3.14" "3.14" 28 | , testCase "Create a boolean" $ do 29 | good "" "-n true" "true" 30 | good "" "-n t" "true" 31 | good "" "-n false" "false" 32 | good "" "-n f" "false" 33 | , testCase "Create null" $ do 34 | good "" "-n null" "null" 35 | good "" "-n n" "null" 36 | , testCase "Create array" $ do 37 | good "" "-n array" "[]" 38 | good "" "-n []" "[]" 39 | 40 | , testCase "Insert into object" $ do 41 | good "" "-n {} -n 1 -i a" "{\"a\":1}" 42 | good "{\"a\":1}" "-n 2 -i b" "{\"a\":1,\"b\":2}" 43 | , testCase "Append to array" $ do 44 | good "" "-n [] -n 1 -i append" "[1]" 45 | good "[0,1]" "-n 2 -i append" "[0,1,2]" 46 | 47 | , testCase "Extract from object" $ do 48 | good "" "-n {} -n 1 -i a -e a" "1" 49 | , testCase "Extract from array" $ do 50 | good "[1,2,3]" "-e 1" "2" 51 | 52 | , testCase "Get type" $ do 53 | good "1" "-t" "number" 54 | good "\"x\"" "-t" "string" 55 | good "true" "-t" "bool" 56 | good "[]" "-t" "array" 57 | good "{}" "-t" "object" 58 | good "null" "-t" "null" 59 | 60 | , testCase "Print keys" $ do 61 | good "" "-n {} -n 0 -i a -n 1 -i b -k" "a\nb" 62 | 63 | , testCase "String" $ do 64 | good "" "-s hey" "\"hey\"" 65 | , testCase "Unstring" $ do 66 | good "" "-s hey -u" "hey" 67 | good "" "-n 3 -u" "3" 68 | good "" "-n 3.14159 -u" "3.14159" 69 | good "" "-n null -u" "null" 70 | good "" "-n true -u" "true" 71 | 72 | , testCase "Across" $ do 73 | good "[1,null]" "-a -t" "number\nnull" 74 | 75 | , testCase "Length" $ do 76 | good "[1,2]" "-n 3 -i append -l" "3" 77 | 78 | , testCase "Errors" $ do 79 | jays "" ["-n", "2", "-i", "foo"] @?= ("jays: error in -i", False) 80 | jays "" ["-Q", "-n", "2", "-i", "foo"] @?= ("", False) 81 | ] 82 | 83 | -- Summary of jshon keywords: 84 | -- 85 | -- -Q (quiet) no error output 86 | -- -a (across) maps remaining actions 87 | -- -e (extract) index into objects/arrays 88 | -- -i (insert) inserts into objects/arrays 89 | -- -j (literal) prints encoded JSON 90 | -- -k (keys) prints keys 91 | -- -n (nonstring) makes a JSON element 92 | -- -s (string) makes a JSON string 93 | -- -u (unstring) prints unquoted string or simple type 94 | -------------------------------------------------------------------------------- /src/restless-git/.gitignore: -------------------------------------------------------------------------------- 1 | /dist 2 | -------------------------------------------------------------------------------- /src/restless-git/Makefile: -------------------------------------------------------------------------------- 1 | all: default.nix nix; nix-shell --command 'cabal build' 2 | default.nix: restless-git.cabal; cabal2nix . > default.nix 3 | nix: default.nix shell.nix 4 | nix-shell --command \ 5 | 'cabal configure --enable-tests' 6 | 7 | .PHONY: all nix 8 | -------------------------------------------------------------------------------- /src/restless-git/README.md: -------------------------------------------------------------------------------- 1 | # restless-git 2 | 3 | In order to more easily use Git repositories as a simple state store 4 | for applications, we made this library. 5 | -------------------------------------------------------------------------------- /src/restless-git/restless-git.cabal: -------------------------------------------------------------------------------- 1 | name: restless-git 2 | version: 0.7 3 | category: Git 4 | synopsis: Easy Git repository serialization 5 | description: 6 | This is an opinionated library for reading and writing 7 | Haskell data from/to Git repositories. 8 | homepage: https://github.com/dapphub/dapptools 9 | license: GPL-3 10 | license-file: COPYING 11 | author: Mikael Brockman 12 | maintainer: mikael@brockman.se 13 | build-type: Simple 14 | cabal-version: >=1.10 15 | 16 | library 17 | hs-source-dirs: src 18 | default-language: Haskell2010 19 | ghc-options: -Wall 20 | exposed-modules: 21 | Restless.Git 22 | build-depends: 23 | base == 4.*, 24 | bytestring >= 0.10, 25 | containers >= 0.5, 26 | text >= 1.2, 27 | time >= 1.8, 28 | HSH >= 2.1, 29 | clock >= 0.7 30 | 31 | test-suite test 32 | default-language: Haskell2010 33 | hs-source-dirs: test 34 | ghc-options: -Wall 35 | type: exitcode-stdio-1.0 36 | main-is: Test.hs 37 | build-depends: 38 | base == 4.*, 39 | bytestring >= 0.10, 40 | containers >= 0.5, 41 | restless-git, 42 | tasty >= 1.0, 43 | tasty-hunit >= 0.10, 44 | temporary >= 1.1, 45 | text >= 1.2 46 | -------------------------------------------------------------------------------- /src/restless-git/shell.nix: -------------------------------------------------------------------------------- 1 | { dapphub ? import ../.. {} }: 2 | let 3 | inherit (dapphub) pkgs; 4 | f = import ./default.nix; 5 | haskellPackages = pkgs.haskellPackages.override { 6 | overrides = (self: super: { 7 | ghc = super.ghc // { withPackages = super.ghc.withHoogle; }; 8 | ghcWithPackages = self.ghc.withPackages; 9 | }); 10 | }; 11 | drv = haskellPackages.callPackage f {}; 12 | in 13 | if pkgs.lib.inNixShell then drv.env else drv 14 | -------------------------------------------------------------------------------- /src/restless-git/test/Test.hs: -------------------------------------------------------------------------------- 1 | {-# Language LambdaCase #-} 2 | {-# Language NamedFieldPuns #-} 3 | {-# Language OverloadedStrings #-} 4 | {-# Language PatternSynonyms #-} 5 | {-# Language RecordWildCards #-} 6 | {-# Language ViewPatterns #-} 7 | 8 | import Restless.Git 9 | 10 | import Test.Tasty 11 | import Test.Tasty.HUnit 12 | 13 | import Data.ByteString (ByteString) 14 | import Data.Set (toList) 15 | import System.IO.Temp (withSystemTempDirectory) 16 | import Text.Read (readMaybe) 17 | 18 | import qualified Data.ByteString.Char8 as C8 19 | import qualified Data.Set as Set 20 | 21 | main :: IO () 22 | main = defaultMain tests 23 | 24 | tests :: TestTree 25 | tests = testGroup "roundtrip" 26 | [ testCase "simple example" roundtripExample ] 27 | 28 | data Example = Example 29 | { foo :: Int 30 | , bar :: Int 31 | } deriving (Eq, Show) 32 | 33 | readBytesMaybe :: Read a => ByteString -> Maybe a 34 | readBytesMaybe = readMaybe . C8.unpack 35 | 36 | pattern Reads :: Read a => a -> ByteString 37 | pattern Reads x <- (readBytesMaybe -> Just x) 38 | 39 | class Filing a where 40 | fromFiles :: [File] -> a 41 | toFiles :: a -> [File] 42 | 43 | instance Filing Example where 44 | fromFiles = foldl f (Example 0 0) 45 | where 46 | f :: Example -> File -> Example 47 | f x = \case 48 | File (Path ["example", "foo"] "x") (Reads foo) -> 49 | x { foo } 50 | File (Path ["example", "bar"] "x") (Reads bar) -> 51 | x { bar } 52 | _ -> 53 | x 54 | toFiles Example {..} = 55 | [ File (Path ["example", "foo"] "x") (C8.pack (show foo)) 56 | , File (Path ["example", "bar"] "x") (C8.pack (show bar)) 57 | ] 58 | 59 | roundtripExample :: Assertion 60 | roundtripExample = do 61 | let x = Example 5 7 62 | y <- withSystemTempDirectory "restless-git-test" $ \path -> do 63 | make path 64 | save path "hello" (Set.fromList (toFiles x)) 65 | (fromFiles . toList) <$> load path 66 | assertEqual "roundtrip failed" x y 67 | -------------------------------------------------------------------------------- /src/seth/Makefile: -------------------------------------------------------------------------------- 1 | default: test 2 | 3 | SHELL = bash 4 | dirs = {bin,libexec} 5 | prefix ?= /usr/local 6 | 7 | dirs:; mkdir -p $(prefix)/$(dirs) 8 | files = $(shell ls -d $(dirs)/*) 9 | install:; cp -r -n $(dirs) $(prefix) 10 | link: uninstall dirs; for x in $(files); do \ 11 | ln -s `pwd`/$$x $(prefix)/$$x; done 12 | uninstall:; rm -rf $(addprefix $(prefix)/,$(files)) 13 | 14 | test: 15 | grep '^#!/usr/bin/env bash' libexec/*/* | cut -d: -f1 | xargs shellcheck --exclude=2001 --exclude=SC2207 16 | 17 | .PHONY: default dirs install link uninstall test 18 | -------------------------------------------------------------------------------- /src/seth/TODO: -------------------------------------------------------------------------------- 1 | - eth_newBlockFilter 2 | - eth_newPendingTransactionFilter 3 | 4 | [TODO: Rename to `--abi-decode-result'?] 5 | Usage: seth --abi-decode ()() 6 | 7 | [TODO: Add `-h' option?] 8 | Usage: seth balance [-B ] 9 | 10 | [TODO: Add argument to find the number of a specific block?] 11 | Usage: seth block-number 12 | 13 | [TODO: Allow to be `current' (also defaulting to `latest')?] 14 | [TODO: Allow setting the second parameter of `eth_getBlockByHash'?] 15 | Usage: seth block [-j|--json] [] 16 | 17 | [TODO: Allow passing through standard input?] 18 | Usage: seth --from-ascii ... 19 | 20 | [TODO: Add `-h' option?] 21 | Usage: seth gas-price 22 | 23 | [TODO: Allow passing through standard input?] 24 | Usage: seth keccak 25 | 26 | [TODO: Allow more than one address?] 27 | [TODO: Allow other filter options?] 28 | Usage: seth logs [-B ] [--follow]
29 | 30 | [TODO: Add `-h' option?] 31 | Usage: seth ls 32 | 33 | [TODO: Allow passing through standard input?] 34 | Usage: seth sign [-F ] 35 | 36 | [TODO: Remove?] 37 | Usage: seth --to-wei [] 38 | -------------------------------------------------------------------------------- /src/seth/bin/seth: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | PATH=${0%/*/*}/libexec/seth:$PATH seth "$@" 4 | -------------------------------------------------------------------------------- /src/seth/default.nix: -------------------------------------------------------------------------------- 1 | { lib, stdenv, fetchFromGitHub, makeWrapper, glibcLocales, solc, nix 2 | , bc, coreutils, curl, ethsign, git, gnused, jq, jshon, nodejs, tre, perl 3 | , gnugrep, hevm, shellcheck, dapptoolsSrc }: 4 | 5 | stdenv.mkDerivation rec { 6 | name = "seth-${version}"; 7 | version = "0.12.0"; 8 | src = ./.; 9 | 10 | nativeBuildInputs = [ nodejs makeWrapper shellcheck ]; 11 | dontBuild = true; 12 | doCheck = true; 13 | checkTarget = "test"; 14 | makeFlags = ["prefix=$(out)"]; 15 | 16 | postInstall = 17 | let 18 | path = lib.makeBinPath [ 19 | bc coreutils curl ethsign git gnused nix jq hevm jshon nodejs tre perl solc 20 | gnugrep 21 | ]; 22 | in 23 | '' 24 | wrapProgram "$out/bin/seth" \ 25 | --prefix PATH : ${path} \ 26 | --set DAPPTOOLS ${dapptoolsSrc} \ 27 | ${lib.optionalString (glibcLocales != null) '' 28 | --set LOCALE_ARCHIVE ${glibcLocales}/lib/locale/locale-archive 29 | ''} 30 | ''; 31 | 32 | # the patching of nodejs shebangs is needed by the seth invocations in 33 | # src/dapp-tests/integration/tests.sh. 34 | # that's also the reason why nodejs is added to nativeBuildInputs 35 | postFixup = '' 36 | patchShebangs $out/libexec/seth 37 | ''; 38 | 39 | meta = { 40 | description = "Command-line client for talking to Ethereum nodes"; 41 | homepage = https://github.com/dapphub/dapptools/src/seth/; 42 | maintainers = [lib.maintainers.dbrock]; 43 | license = lib.licenses.gpl3; 44 | inherit version; 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---abi-constructor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | console.log(`constructor(${(JSON.parse( 3 | require("fs").readFileSync("/dev/stdin", { encoding: "utf-8" }) 4 | ).filter( 5 | x => x.type == "constructor" 6 | )[0] || { inputs: [] }).inputs.map(x => x.type).join(",")})`) 7 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---abi-decode: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | //seth---abi-decode -- extract return values from hexdata 3 | const usage = `Usage: seth --abi-decode ()( 4 | Decode according to ( are ignored).`; 5 | if (process.argv.length == 4) { 6 | if (process.argv[2].indexOf(')(') >= 0) { 7 | // silence warnings we don't care about 8 | const log = console.log 9 | console.log = () => {}; 10 | const ethers = require("./ethers.min.js"); 11 | console.log = log; 12 | const sig = process.argv[2].replace(')(', ') returns ('); 13 | const hexdata = process.argv[3].indexOf('0x') == 0 ? process.argv[3] : "0x" + process.argv[3]; 14 | try { 15 | const funcs = new ethers.utils.Interface(['function ' + sig]).functions; 16 | console.log(funcs[Object.keys(funcs)[0]].decode(hexdata).join('\n')) 17 | } catch (e) { 18 | console.error(e.toString()) 19 | process.exit(1) 20 | } 21 | } else { 22 | const {execFileSync} = require('child_process'); 23 | try { 24 | const yes = execFileSync("seth", 25 | ["--to-hex", 26 | process.argv[3]] 27 | ).toString().replace('\n','') 28 | console.log(yes) 29 | } catch(e) { 30 | console.error(e) 31 | process.exit(1) 32 | } 33 | } 34 | } else { 35 | console.error(usage) 36 | process.exit(1) 37 | } 38 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---abi-event-json: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | seth abi "event $1;" 4 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---abi-function-json: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | if [[ $1 = *\)\(* ]]; then 4 | sig=${1/)(/) public returns (} 5 | else 6 | sig="$1 public" 7 | fi 8 | 9 | seth abi "function $sig" | jq '.[0]' -c 10 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---calldata-decode: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const usage = `Usage: seth --calldata-decode ()( 3 | Decode according to ( are ignored).`; 4 | if (process.argv.length == 4 && 5 | process.argv[2].indexOf('(') >= 0) { 6 | // silence warnings we don't care about 7 | const log = console.log 8 | console.log = () => {}; 9 | const ethers = require("./ethers.min.js"); 10 | console.log = log; 11 | const sig = process.argv[2]; 12 | const calldata = process.argv[3]; 13 | try { 14 | const sighash = ethers.utils.hexDataSlice(calldata, 0, 4); 15 | const data = ethers.utils.hexDataSlice(calldata, 4); 16 | const funcs = new ethers.utils.Interface(["function " + sig.replace(')(', ') returns (')]).functions; 17 | const func = Object.values(funcs).find(f => f.sighash == sighash); 18 | const decoded = ethers.utils.defaultAbiCoder.decode(func.inputs, data); 19 | console.log(decoded.map(e => e.toString()).join('\n')); 20 | } catch (e) { 21 | console.error(e.toString()) 22 | process.exit(1) 23 | } 24 | } else { 25 | console.error(usage) 26 | process.exit(1) 27 | } 28 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---decode-event: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | //seth---decode-event -- decode hexdata into event form 3 | const usage = "Usage: seth --decode-event "; 4 | if (process.argv.length == 5) { 5 | // silence warnings we don't care about 6 | const log = console.log 7 | console.log = () => {}; 8 | const ethers = require("./ethers.min.js"); 9 | console.log = log; 10 | try { 11 | const events = new ethers.utils.Interface(process.argv[2]).events; 12 | console.log(events[process.argv[3]].decode(process.argv[4]).join('\n')) 13 | } catch (e) { 14 | console.error(e.toString()) 15 | process.exit(1) 16 | } 17 | } else { 18 | console.log(usage) 19 | process.exit(1) 20 | } 21 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---decode-events: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | while read -r event; do seth --decode-event "$event"; done 4 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---decorate-abi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var abi = JSON.parse(process.argv[2]) 3 | var { execFileSync } = require("child_process") 4 | var call = (name, ...args) => execFileSync(name, args, { encoding: "utf-8" }) 5 | 6 | console.log(JSON.stringify(abi.map(x => { 7 | if (x.type == "event") { 8 | var sig = `${x.name}(${x.inputs.map(x => x.type).join(",")})` 9 | var hexdata = call("seth", "--from-ascii", sig).trim() 10 | var topic = call("seth", "keccak", hexdata).trim() 11 | return Object.assign(x, { topic }) 12 | } else { 13 | return x 14 | } 15 | }, null, 2))) 16 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---event-name: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | if (!process.env.SETH_ABI) { 3 | console.error("seth---event-name: error: `SETH_ABI' not set") 4 | process.exit(1) 5 | } 6 | 7 | var topic = process.argv[2] 8 | var abi = JSON.parse(process.env.SETH_ABI) 9 | var event = abi.filter(x => x.topic == topic)[0] 10 | 11 | if (event) { 12 | console.log(event.name) 13 | } 14 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---fail: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo >&2 "$*" 3 | exit 1 4 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---fail-usage: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | basename=${1##*/} 3 | seth >&2 "${basename#seth-}" --help 4 | exit 1 5 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---field: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | grep "^$1\\s" | { read -r _ value && echo "$value"; } 4 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---from-ascii: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---from-ascii -- convert text data into hexdata 3 | ### Usage: seth --from-ascii ... 4 | set -e 5 | [[ $1 ]] || set -- "$(cat)" 6 | printf %s "$*" | seth --from-bin 7 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---from-bin: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---from-bin -- convert binary data into hexdata 3 | ### Usage: seth --from-bin data.hex 4 | ### Read binary data from standard input and print it as hexdata. 5 | set -e 6 | hexdump=$(od -vt x1) 7 | nibbles=$(sed "s/^[0-9]*//" <<<"$hexdump") 8 | hexdata=$(tr -d " \\n" <<<"$nibbles") 9 | echo "0x$hexdata" 10 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---from-fix: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---from-fix -- convert fixed point into specified number of decimals 3 | ### Usage: seth --from-fix 4 | set -e 5 | [[ $# -eq 2 ]] || seth --fail-usage "$0" 6 | 7 | decimals=$1 8 | number=$2 9 | 10 | bc <<<"$number * 10 ^ $decimals / 1" | tr -d '\\\n' # dividing by 1 ensures integer output 11 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---from-wei: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---from-wei -- convert a wei amount into ETH 3 | ### Usage: seth --from-wei [] 4 | set -e 5 | [[ $1 ]] || set -- "$(cat)" 6 | [[ $1 ]] || seth --fail-usage "$0" 7 | set -- "$*" 8 | [[ $1 = *" "* ]] || set -- "$1 eth" 9 | number=${1%% *} unit=${1#* } 10 | # shellcheck disable=2018,2019 11 | unit=$(tr A-Z a-z <<<"$unit") 12 | 13 | case $unit in 14 | wei) scale=0;; 15 | gwei) scale=9;; 16 | eth|ether) scale=18;; 17 | *) seth --fail "${0##*/}: error: unrecognized monetary value: \`$1'" 18 | esac 19 | 20 | number=${number/[eE]/*10^} 21 | number=${number/^+/^} 22 | bc <<<"scale=$scale; $number * 10^-$scale" 23 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---help: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | seth help 4 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---max-int: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---max-int -- print the maximum int of the given bits 3 | ### Usage: seth --max-int [] 4 | set -e 5 | [[ $1 ]] && bits=$1 || bits=256 6 | echo "0x$(bc <<< "obase=16; 2^$bits / 2 - 1" | tr A-F a-f)" 7 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---max-uint: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---max-uint -- print the maximum uint of the given bits 3 | ### Usage: seth --max-uint [] 4 | set -e 5 | [[ $1 ]] && bits=$1 || bits=256 6 | echo "0x$(bc <<< "obase=16; 2^$bits - 1" | tr A-F a-f)" 7 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---min-int: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---min-int -- print the minimum int of the given bits 3 | ### Usage: seth --min-int [] 4 | set -e 5 | [[ $1 ]] && bits=$1 || bits=256 6 | echo "0x$(bc <<< "obase=16; 2^$bits / 2" | tr A-F a-f)" 7 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---nix-run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Usage: seth --nix-run PKG COMMAND... 3 | # Example: 4 | # $ seth --nix-run go-ethereum geth --version 5 | # 6 | # Runs a command with the binaries from a named Nix package in PATH. 7 | 8 | set -e 9 | 10 | have() { command -v "$1" >/dev/null; } 11 | { have nix; } || { 12 | echo >&2 "${0##*/}: error: The Nix package manager is required." 13 | echo >&2 "${0##*/}: error: See https://dapp.tools for installation instructions." 14 | exit 1 15 | } 16 | 17 | expr="$1"; shift 18 | 19 | nix run "(with import $DAPPTOOLS {}; $expr)" -c "$@" 20 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---send-params: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | param() { 3 | if [[ ${!1} ]]; then 4 | if [[ ${!1} = *\ * ]]; then 5 | seth --fail "${0##*/}: error: $1 contains whitespace" 6 | else 7 | if [[ $3 = --address ]]; then 8 | value=$(seth --to-address "${!1}") 9 | elif [[ $3 = --wei ]]; then 10 | value=$(seth --to-wei "${!1}") 11 | value=$(seth --to-hex "$value") 12 | else 13 | value=$(seth --to-hex "${!1}") 14 | fi 15 | echo -s "$value" -i "$2" 16 | fi 17 | fi 18 | } 19 | 20 | param ETH_FROM from --address 21 | param ETH_NONCE nonce 22 | param ETH_VALUE value --wei 23 | 24 | # skip setting ETH_GAS if the NO_GAS var is provided, useful e.g. when 25 | # doing gas estimation since the gas field should be empty 26 | if [[ -z $SETH_PARAMS_NO_GAS ]]; then 27 | param ETH_GAS gas 28 | fi 29 | 30 | if [[ $ETH_PRIO_FEE ]]; then 31 | param ETH_GAS_PRICE maxFeePerGas --wei 32 | param ETH_PRIO_FEE maxPriorityFeePerGas --wei 33 | else 34 | param ETH_GAS_PRICE gasPrice --wei 35 | fi 36 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---show-json: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | show-json() { 5 | if [[ $1 = \"*\" ]]; then 6 | unquoted=$(jshon <<<"[$1]" -a -u) 7 | if is-short-hexnum 20 "$unquoted"; then 8 | show-hexnum "$unquoted" 9 | else 10 | echo "$unquoted" 11 | fi 12 | else 13 | echo "$1" 14 | fi 15 | } 16 | 17 | is-short-hexnum() { 18 | [[ ${#2} -lt $1 && $2 =~ 0x[[:xdigit:]]+ ]] 19 | } 20 | 21 | show-hexnum() { 22 | digits=${1:2} 23 | bc <<<"ibase=16; $(tr a-f A-F <<<"$digits")" 24 | } 25 | 26 | if [[ $SETH_JSON ]]; then 27 | jshon 28 | else 29 | json=$(cat) 30 | case $json in 31 | \[*\]) jshon <<<"$json" -a -j | 32 | while read -r item; do 33 | show-json "$item" 34 | done;; 35 | \{*\}) jshon <<<"$json" -k | 36 | while read -r key; do 37 | value=$(jshon <<<"$json" -e "$key" -j) 38 | value=$(show-json "$value") 39 | printf "%-${SETH_KEY_WIDTH-23}s %s\\n" "$key" "$value" 40 | done | sort;; 41 | \"*\") show-json "$json";; 42 | *) echo "$json";; 43 | esac 44 | fi 45 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---to-address: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---to-address -- convert hex into checksummed address 3 | ### Usage: seth --to-address 4 | set -e 5 | [[ $1 ]] || set -- "$(cat)" 6 | hexdata=$(seth --to-hexdata "$@") 7 | [[ ${#hexdata} = 42 ]] || 8 | seth --fail "${0##*/}: error: bad address: \`$hexdata'" 9 | seth --to-checksum-address "$hexdata" 10 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---to-ascii: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---to-ascii -- convert hexdata into text data 3 | ### Usage: seth --to-ascii [] 4 | set -e 5 | [[ $1 ]] || set -- "$(cat)" 6 | hexdata=$(seth --to-hexdata "$@") 7 | format=$(sed 's/../\\x&/g' <<<"${hexdata#0x}") 8 | bash -c "printf '$format\\n'" 9 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---to-bytes32: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---to-bytes32 -- convert hexdata into bytes32 value 3 | ### Usage: seth --to-bytes32 [] 4 | set -e 5 | [[ $1 ]] || set -- "$(cat)" 6 | printf "0x%-64s\\n" "${1#0x}" | tr ' ' 0 7 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---to-checksum-address: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var keccak256 = require('./sha3.js').keccak256; 3 | 4 | // adapted from https://github.com/ethereumjs/ethereumjs-util/blob/master/index.js#L465 5 | function toChecksumAddress(address) { 6 | address = address.toLowerCase().replace('0x','') 7 | var hash = keccak256(address).toString('hex') 8 | var ret = '0x' 9 | 10 | for (let i = 0; i < address.length; i++) { 11 | if (parseInt(hash[i], 16) >= 8) { 12 | ret += address[i].toUpperCase() 13 | } else { 14 | ret += address[i] 15 | } 16 | } 17 | 18 | console.log(ret) 19 | } 20 | 21 | if (!process.argv[2]) { 22 | console.error("seth---to-checksum-address: error: missing argument") 23 | process.exit(1) 24 | } 25 | var address = process.argv[2]; 26 | toChecksumAddress(address) 27 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---to-dec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---to-dec -- convert hex into decimal 3 | ### Usage: seth --to-dec 4 | set -e 5 | [[ $1 ]] || exec xargs -n1 "$0" 6 | hexdata=$(seth --to-hexdata "$1") 7 | hexnum=${hexdata#0x} 8 | num=$(bc <<<"ibase=16; $(tr a-f A-F <<<"$hexnum")") 9 | # shellcheck disable=SC1003 10 | tr -d '\n\\' <<<"$num" 11 | echo 12 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---to-fix: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---to-fix -- convert wei into fixed point 3 | ### Usage: seth --to-fix 4 | set -e 5 | [[ $1 ]] || seth --fail-usage "$0" 6 | [[ $2 ]] || set -- "$1" "$(cat)" 7 | [[ $# = 2 ]] || seth --fail-usage "$0" 8 | [[ ${#2} -lt $1 ]] && exec printf "0.%0${1}d\\n" "$2" 9 | whole_digits=$((${#2} - $1)) 10 | whole_part=${2:0:$whole_digits} 11 | echo "${whole_part:-0}.${2:$whole_digits}" 12 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---to-hex: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---to-hex -- convert decimal into hex 3 | ### Usage: seth --to-hex 4 | set -e 5 | [[ $1 ]] || set -- "$(cat)" 6 | if [[ $1 =~ ^[[:digit:]]+$ ]]; then 7 | hexnum=$(bc <<<"obase=16; $1") 8 | echo "0x$(tr A-F a-f <<<"$hexnum")" 9 | elif [[ $1 = 0x* ]]; then 10 | seth --to-hexdata "$1" 11 | elif [[ $1 =~ ^[[:xdigit:]]+$ ]]; then 12 | seth --fail "${0##*/}: error: missing \`0x' prefix: \`$1'" 13 | else 14 | seth --fail "${0##*/}: error: bad number: \`$1'" 15 | fi 16 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---to-hexdata: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### Usage: seth --to-hexdata [||<@tag>] 3 | ### 4 | ### Output lowercase, 0x-prefixed hex, converting from the 5 | ### input provided as an argument or stdin, which can be: 6 | ### - mixed case hex with or without 0x prefix 7 | ### - 0x prefixed hex, concatenated with a ':' 8 | ### - absolute path to file 9 | ### - @tag, where $TAG is defined in environment variables 10 | 11 | set -e 12 | 13 | if [[ $# = 0 ]]; then 14 | set -- "$(cat)" 15 | elif [[ $# != 1 ]]; then 16 | seth --fail-usage "$0" 17 | fi 18 | 19 | if [[ $1 = @* ]]; then 20 | value=$(seth lookup "$1") 21 | "$0" "$value" 22 | elif [[ $1 =~ / ]]; then 23 | "$0" <"$1" 24 | elif [[ $1 =~ ^0x[[:xdigit:]]*$ ]]; then 25 | tr A-F a-f <<<"$1" 26 | elif [[ $1 =~ ^[[:xdigit:]]+$ ]]; then 27 | echo "0x$(tr A-F a-f <<<"$1")" 28 | elif [[ $1 =~ ^(0x[[:xdigit:]]*:)+0x[[:xdigit:]]*$ ]]; then 29 | echo "0x$(sed -E -e 's/(^0x|:0x)//g' <<<"$1" | tr A-F a-f)" 30 | else 31 | seth --fail "${0##*/}: error: invalid hexdata: \`$1'" 32 | fi 33 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---to-int256: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---to-int256 -- convert an integer into int256 value 3 | ### Usage: seth --to-int256 4 | set -e 5 | [[ $1 ]] || set -- "$(cat)" 6 | export BC_LINE_LENGTH=100 7 | seth --to-uint256 "$(bc <<< "(2^256 * ($1 < 0)) + $1")" 8 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---to-uint256: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---to-uint256 -- convert an integer into uint256 value 3 | ### Usage: seth --to-uint256 4 | set -e 5 | [[ $1 ]] || set -- "$(cat)" 6 | hex=$(seth --to-hex "$1") 7 | printf "0x%64s\\n" "${hex#0x}" | tr ' ' 0 8 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---to-wei: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth---to-wei -- convert an ETH amount into wei 3 | ### Usage: seth --to-wei [] 4 | set -e 5 | [[ $1 ]] || set -- "$(cat)" 6 | [[ $1 ]] || seth --fail-usage "$0" 7 | set -- "$*" 8 | [[ $1 = *" "* ]] || set -- "$1 wei" 9 | number=${1%% *} unit=${1#* } 10 | # shellcheck disable=2018,2019 11 | unit=$(tr A-Z a-z <<<"$unit") 12 | 13 | case $unit in 14 | wei) scale=0;; 15 | gwei) scale=9;; 16 | eth|ether) scale=18;; 17 | *) seth --fail "${0##*/}: error: unrecognized monetary value: \`$1'" 18 | esac 19 | 20 | bc <<<"$number * 10 ^ $scale / 1" 21 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---to-word: -------------------------------------------------------------------------------- 1 | seth---to-uint256 -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---use: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | function usage() { 5 | echo >&2 "Usage: seth --use ..." 6 | echo >&2 "Example:" 7 | echo >&2 8 | echo >&2 " $ seth --use solc:0.4.11 combined-json" 9 | echo >&2 10 | exit 1 11 | } 12 | 13 | [[ "$#" -gt 0 ]] || usage 14 | 15 | query() { 16 | nix-env -q --installed --out-path --no-name "$1" 2>/dev/null 17 | } 18 | 19 | shopt -s extglob 20 | case $1 in 21 | # package spec e.g. solc:0.4.12 22 | solc:[0-9].+([0-9.])) 23 | solc="solc-${1#solc:}" 24 | if store_path=$(query "solc-${1#solc:}"); then 25 | bin="$store_path/bin/solc" 26 | elif store_path=$(query "solc-static-${1#solc:}"); then 27 | bin="$store_path/bin/$solc" 28 | else 29 | bin="" 30 | fi 31 | ;; 32 | # some other solc binary name 33 | solc*) 34 | solc="$1" 35 | set +e 36 | bin="$(type -p "$solc")" 37 | ;; 38 | # if there's a '/', interpret as a path 39 | */*) 40 | bin="$1" 41 | ;; 42 | *) 43 | echo >&2 "${0##*/}: unrecognized package spec: $1" 44 | exit 1 45 | esac 46 | shift 47 | 48 | [[ "$#" -gt 0 ]] || usage 49 | 50 | if [[ -z "$bin" ]]; then 51 | echo >&2 "${0##*/}: Could not find ${solc} in your path or nix store." 52 | echo >&2 "Temporarily installing ${solc}..." 53 | echo >&2 "Tip: run \`nix-env -f https://github.com/dapphub/dapptools/archive/master.tar.gz -iA solc-static-versions.${solc//[-.]/_}\` for a lasting installation of this version." 54 | seth --nix-run "seth.override {solc = pkgs.runCommand \"solc\" { } \"mkdir -p \$out/bin; ln -s \${solc-static-versions.${solc//[-.]/_}}/bin/${solc} \$out/bin/solc\";}" seth "$@" 55 | 56 | else 57 | set -e 58 | SOLCBIN="$(realpath -e "${bin}")" 59 | fi 60 | 61 | DAPP_SOLC="$SOLCBIN" seth "$@" 62 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---version: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | cat <<. 3 | seth 0.12.0 4 | Copyright (C) 2016-2021 Daniel Brockman 5 | License: GNU GPL version 3 or later . 6 | This is free software: you are free to change and redistribute it. 7 | There is NO WARRANTY, to the extent permitted by law. 8 | . 9 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth---warn: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo >&2 "${1##*/}: warning: ${*:2}" 3 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-4byte: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-4byte -- prints the response from querying 4byte.directory for a given function signature 3 | ### Usage: seth 4byte [] 4 | ### 5 | ### Takes a 4 byte function signature and prints matching functions from 4byte.directory. This will also strip 6 | ### any appended calldata after the first four bytes 7 | ### 8 | ### When the --verbose option is used, the full JSON response is printed, otherwise just text signatures are printed 9 | 10 | set -e 11 | [[ $# -eq 1 ]] || seth --fail-usage "$0" 12 | 13 | if [[ $SETH_VERBOSE ]]; then 14 | curl -s "https://www.4byte.directory/api/v1/signatures/?hex_signature=${1:0:10}" | jq . 15 | else 16 | curl -s "https://www.4byte.directory/api/v1/signatures/?hex_signature=${1:0:10}" | jq -r '.results[] | .text_signature' 17 | fi 18 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-4byte-decode: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-4byte-decode -- queries 4byte.directory to find a matching signature, then decodes the calldata with it 3 | ### Usage: seth 4byte-decode [] 4 | ### 5 | ### Queries 4byte.directory to find matching signatures and prompts the user to to select one. The selected 6 | ### signature will be used to decode the calldata. 7 | 8 | set -e 9 | [[ $# -eq 1 ]] || seth --fail-usage "$0" 10 | 11 | if [[ -z $SETH_4BYTE_ID ]]; then 12 | # Function signature ID not specified, prompt user to choose a signature 13 | sigs=$(curl -s "https://www.4byte.directory/api/v1/signatures/?hex_signature=${1:0:10}" | jq '.results[] | .text_signature' ) 14 | PS3="Select a function signature by number: " 15 | select sig in $sigs; do 16 | break 17 | done 18 | echo "" # add a line break for easier reading 19 | else 20 | # Function signature ID was specified, so parse results without user input 21 | results=$(curl -s "https://www.4byte.directory/api/v1/signatures/?hex_signature=${1:0:10}" | jq .results[] ) 22 | sigs=$(echo $results | jq '.text_signature') 23 | 24 | # sigs is a string so split it into an array 25 | sigarray=() 26 | for sig in $sigs; do sigarray+=($sig); done 27 | length=${#sigarray[@]} 28 | 29 | # parse the provided ID 30 | if [[ $SETH_4BYTE_ID = earliest ]]; then 31 | # first one added to 4byte is the last in the array 32 | sig=${sigarray[$length-1]} 33 | elif [[ $SETH_4BYTE_ID = latest ]]; then 34 | # last one added to 4byte is the first in the array 35 | sig=${sigarray[0]} 36 | else 37 | # specific ID number provided (if using this option, you may be better off with `seth --calldata-decode`) 38 | query=". | select(.id==$SETH_4BYTE_ID) | .text_signature" 39 | sig=$(echo $results | jq "$query") 40 | fi 41 | fi 42 | 43 | # Exit if no sig found 44 | if [[ -z $sig ]]; then 45 | echo >&2 "seth 4byte-decode: no signature found" 46 | exit 1 47 | elif [[ $SETH_VERBOSE ]]; then 48 | echo "signature: $sig" 49 | fi 50 | 51 | # Remove leading and trailing quotes from JSON, then decode 52 | sig="${sig//\"}" 53 | seth --calldata-decode $sig $1 54 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-4byte-event: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-4byte-event -- prints the response from querying 4byte.directory for a given function topic 3 | ### Usage: seth 4byte-event [] 4 | ### 5 | ### Takes a 32 byte topic and prints the response from querying 4byte.directory for that topic 6 | 7 | set -e 8 | [[ $# -eq 1 ]] || seth --fail-usage "$0" 9 | 10 | if [[ $SETH_VERBOSE ]]; then 11 | curl -s "https://www.4byte.directory/api/v1/event-signatures/?hex_signature=$1" | jq . 12 | else 13 | curl -s "https://www.4byte.directory/api/v1/event-signatures/?hex_signature=$1" | jq '.results[] | .text_signature' 14 | fi 15 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-abi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // silence warnings we don't care about 4 | const log = console.log 5 | console.log = () => {}; 6 | 7 | const ethers = require("./ethers.min.js"); 8 | 9 | console.log = log; 10 | 11 | const sig = process.argv[2]; 12 | if (!sig) { 13 | console.error("Usage: seth-abi ") 14 | process.exit(1); 15 | } 16 | 17 | try { 18 | console.log(JSON.stringify([ethers.utils.parseSignature(sig)])); 19 | } catch (e) { 20 | console.error(`seth-abi: error: ${e.message}`); 21 | process.exit(1); 22 | } 23 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-abi-encode: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-abi-encode -- ABI encode values, and prints the encoded values without the function signature 3 | ### Usage: seth abi-encode [] 4 | ### 5 | ### ABI encode values based on a provided function signature, slice off the leading the function signature, 6 | ### and print the result. It does not matter what the name of the function is, as only the types and values 7 | ### affect the output. 8 | 9 | set -e 10 | 11 | x=$(seth calldata $@); # generate full calldata based on function signature 12 | echo "0x${x:10}" # slice off the function signature and only keep the encoded values 13 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-accounts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | if [[ -z $ETH_RPC_ACCOUNTS ]]; then 4 | ethsign ls 5 | else 6 | seth rpc eth_accounts | awk "{print \$1 \" $ETH_RPC_URL\"}" 7 | fi 8 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-age: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-age -- show the timestamp of the latest block 3 | set -e 4 | timestamp=$(seth block "${ETH_BLOCK-latest}" timestamp) 5 | date -d@"$timestamp" 6 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-balance: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-balance -- show the balance of any account on the blockchain 3 | ### Usage: seth balance [-B ] 4 | ### Print the balance of in wei. 5 | ### 6 | ### With `-B ', print the balance as of . 7 | set -e 8 | [[ $1 ]] || seth --fail-usage "$0" 9 | account=$1 10 | [[ $account = @* ]] && account=$(seth lookup "$account") 11 | jshon+=(-s "$account" -i append) 12 | jshon+=(-s "${ETH_BLOCK-latest}" -i append) 13 | balance=$(seth rpc eth_getBalance -- "${jshon[@]}") 14 | [[ $balance = 0x* ]] && balance=$(seth --to-dec "$balance") 15 | echo "$balance" 16 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-basefee: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | seth block "${1:-latest}" baseFeePerGas 4 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-block: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-block -- print a table of information about a specific block 3 | ### Usage: seth block [-j|--json] [] 4 | ### Print a table of information about . 5 | ### If is given, print only the value of that field. 6 | set -e 7 | [[ $# = [12] ]] || seth --fail-usage "$0" 8 | 9 | if [[ $1 = 0x* ]]; then 10 | if [[ $SETH_FULL_BLOCK ]]; then 11 | block=$(seth get-full-block-by-hash "$1") 12 | else 13 | block=$(seth get-block-by-hash "$1") 14 | fi 15 | else 16 | if [[ $SETH_FULL_BLOCK ]]; then 17 | block=$(seth get-full-block-by-number "$1") 18 | else 19 | block=$(seth get-block-by-number "$1") 20 | fi 21 | fi 22 | 23 | if [[ $block = null ]]; then 24 | seth --fail "${0##*/}: error: no such block: $1" 25 | elif [[ $2 ]]; then 26 | seth --field "$2" <<<"$block" 27 | else 28 | echo "$block" 29 | fi 30 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-block-number: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | seth rpc eth_blockNumber 4 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-bundle-source: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-bundle-source -- fetch source and compile contract 3 | ### Usage: seth bundle-source
[] 4 | ### 5 | ### Requires an etherscan api key 6 | ### 7 | ### Use `--dir` to control where the contract source is written (default is cwd) 8 | ### 9 | set -e 10 | 11 | [[ -z "$1" ]] && seth --fail-usage 12 | 13 | ETHERSCAN_SRC=$(seth etherscan-source "$1") 14 | 15 | SOLC_VERSION=$(jq '.CompilerVersion' <<< "$ETHERSCAN_SRC") 16 | SOLC_VERSION=${SOLC_VERSION/'"'} 17 | SOLC_VERSION=${SOLC_VERSION/v} 18 | SOLC_VERSION=${SOLC_VERSION/+*} 19 | 20 | SOURCE="$(jq -r '.SourceCode' <<< "$ETHERSCAN_SRC" | tr -d '\r')" 21 | 22 | SETH_DIR=${SETH_DIR:-.} 23 | 24 | case "$SOURCE" in 25 | \{*\}) # standard-json 26 | # for some reason etherscan surrounds the actual json with '{}' 27 | SOURCE="${SOURCE/#\{\{/\{}" 28 | SOURCE="${SOURCE/%\}\}/\}}" 29 | 30 | # write all source files to SETH_DIR 31 | for x in $(echo "$SOURCE" | jq '.sources | keys | .[]' -r); do 32 | mkdir -p "$SETH_DIR/$(dirname "$x")" 33 | echo "$SOURCE" | jq ".sources.\"$x\".content" -r > "$SETH_DIR/$x" 34 | done; 35 | export DAPP_SOLC_JSON="$SOURCE" 36 | seth --use solc:"${SOLC_VERSION}" solc --dir "$SETH_DIR" 37 | ;; 38 | 39 | *) # flattened file 40 | NAME="$(jq -r '.ContractName' <<< "$ETHERSCAN_SRC")" 41 | FILE="$SETH_DIR/$NAME.sol" 42 | echo "$SOURCE" > "$FILE" 43 | OPT=$(jq -r '.OptimizationUsed' <<< "$ETHERSCAN_SRC") 44 | if [[ "$OPT" -ne 0 ]]; then 45 | RUNS=$(jq -r '.Runs' <<< "$ETHERSCAN_SRC") 46 | export DAPP_SOLC_OPTIMIZE=true 47 | export DAPP_SOLC_OPTIMIZE_RUNS=$RUNS 48 | fi 49 | seth --use solc:"${SOLC_VERSION}" solc "$FILE" 50 | ;; 51 | esac 52 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-calldata: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-calldata -- pack a signature and a list of arguments into calldata 3 | ### Usage: seth calldata [] 4 | ### or: seth calldata 5 | ### or: seth calldata 6 | ### 7 | ### Pack and into data suitable for passing to `seth call'. 8 | ### If has the form `()', pack / into calldata. 9 | ### 10 | ### If contains a slash character, treat it as a file name to read. 11 | ### Otherwise, ensure begins with `0x' and treat it as hexdata. 12 | set -e 13 | if [[ $1 =~ ^([^\(]+)\( ]]; then 14 | abi=$(seth --abi-function-json "$1") 15 | shift 16 | args=() 17 | for arg; do 18 | [[ $arg = @* ]] && arg=$(seth lookup "$arg") 19 | args+=(--arg "$arg") 20 | done 21 | calldata=$( 22 | hevm abiencode --abi "$abi" "${args[@]}" 23 | ) 24 | if [[ $calldata = error* ]]; then 25 | echo >&2 "hevm: $calldata" 26 | exit 1 27 | else 28 | echo "0x${calldata#0x}" 29 | fi 30 | elif [[ $2 ]]; then 31 | seth --fail-usage "$0" 32 | else 33 | seth --to-hexdata "$1" 34 | fi 35 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-chain: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-chain -- print the symbolic name of the current blockchain 3 | ### Print the name of the current chain (`ethlive', `kovan', etc). 4 | set -e 5 | genesis=$(seth block 0 hash) 6 | case $genesis in 7 | 0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3) 8 | case $(seth block 1920000 hash 2>/dev/null || echo null) in 9 | 0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f) 10 | echo etclive;; 11 | *) 12 | echo ethlive;; 13 | esac;; 14 | 0xa3c565fc15c7478862d50ccd6561e3c06b24cc509bf388941c25ea985ce32cb9) 15 | echo kovan;; 16 | 0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d) 17 | echo ropsten;; 18 | 0x7ca38a1916c42007829c55e69d3e9a73265554b586a499015373241b8a3fa48b) 19 | echo optimism-mainnet;; 20 | 0x02adc9b449ff5f2467b8c674ece7ff9b21319d76c4ad62a67a70d552655927e5) 21 | echo optimism-kovan;; 22 | 0x7ee576b35482195fc49205cec9af72ce14f003b9ae69f6ba0faef4514be8b442) 23 | # arbitrum mainnet and arbitrum rinkeby have the same genesis block 24 | # use the next block to discriminate between the two 25 | case $(seth block 1 hash 2>/dev/null || echo null) in 26 | 0xe0594250efac73640aeff78ec40aaaaa87f91edb54e5af926ee71a32ef32da34) 27 | echo arbitrum-mainnet;; 28 | 0x5b754d2c394d7e8852f5ef8ef97314cb4b566b027e5b943bee2b0b2d53fdc43e) 29 | echo arbitrum-rinkeby;; 30 | *) 31 | echo unknown;; 32 | esac;; 33 | 0x0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303) 34 | echo morden;; 35 | 0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177) 36 | echo rinkeby;; 37 | 0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a) 38 | echo goerli;; 39 | 0x14c2283285a88fe5fce9bf5c573ab03d6616695d717b12a127188bcacfc743c4) 40 | echo kotti;; 41 | 0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34) 42 | echo bsctest;; 43 | 0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b) 44 | echo bsc;; 45 | 0xa9c28ce2141b56c474f1dc504bee9b01eb1bd7d1a507580d5519d4437a97de1b) 46 | echo polygon;; 47 | 0x7b66506a9ebdbf30d32b43c5f15a3b1216269a1ec3a75aa3182b86176a2b1ca7) 48 | echo polygon-mumbai;; 49 | 0x00000000000003e83fddf1e9330f0a8691d9f0b2af57b38c3bb85488488a40df) 50 | echo fantom;; 51 | 0x31ced5b9beb7f8782b014660da0cb18cc409f121f408186886e1ca3e8eeca96b) 52 | case $(seth block 1 hash 2>/dev/null || echo null) in 53 | 0xdcfce25a3318f7e6ac4d5ae7f9f3644e39b2ad411ef218d04ca65fec4a1bf737) 54 | echo avax-mainnet;; 55 | 0x738639479dc82d199365626f90caa82f7eafcfe9ed354b456fb3d294597ceb53) 56 | echo avax-fuji;; 57 | *) 58 | echo unknown;; 59 | esac;; 60 | *) 61 | echo unknown;; 62 | esac 63 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-chain-id: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | seth rpc eth_chainId 4 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-client: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | seth rpc web3_clientVersion 4 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-code: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-code -- print the bytecode of an object on the blockchain 3 | ### Usage: seth code [-B ]
4 | ### Print the bytecode of the object at
. 5 | ### 6 | ### With `-B ', print the bytecode as of . 7 | set -e 8 | [[ $# = 1 ]] || seth --fail-usage "$0" 9 | ADDRESS=$(seth --to-address "$@") 10 | jshon+=(-s "$ADDRESS" -i append) 11 | jshon+=(-s "${ETH_BLOCK-latest}" -i append) 12 | seth rpc eth_getCode -- "${jshon[@]}" | seth --to-hex 13 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-curl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | [[ $SETH_DEBUG_CURL ]] && set -x 4 | curl -fsS "$@" || { 5 | code=$? 6 | # TODO(mariano): fix this 7 | # shellcheck disable=2154 8 | [[ $code = 22 ]] && (set -x; : "${command[@]}") 9 | exit $code 10 | } 11 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-debug: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-debug -- debug a transaction in hevm interactive 3 | ### Usage: seth debug [] 4 | ### 5 | ### Runs all the transactions in the block to get the correct state 6 | ### then executes the given transaction in debug mode 7 | ### 8 | ### Unless `--no-src` is given, source code for the `to` address 9 | ### will be passed along to hevm for better debugging xp 10 | set -e 11 | 12 | state=$(TMPDIR=. mktemp -d hevm.libs.XXXXX -p /tmp) 13 | 14 | export GIT_CONFIG_NOSYSTEM=1 15 | export GIT_AUTHOR_NAME=hevm 16 | export GIT_AUTHOR_EMAIL=hevm@dapphub.com 17 | export GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME 18 | export GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL 19 | gitopts=(-q --no-verify --no-gpg-sign --allow-empty -m "dapp test") 20 | ( cd "$state" || exit ; git init -q && git add . && git commit "${gitopts[@]}" ) 21 | 22 | targetTx=$(seth tx "$1") 23 | 24 | # TODO: scary rm -rf 25 | tidy() { 26 | [[ "$SRCDIR" ]] && rm -rf "$SRCDIR" 27 | rm -rf "$state" 28 | } 29 | trap tidy SIGINT SIGTERM 30 | 31 | if [[ -z "$SETH_NOSRC" ]]; then 32 | echo >&2 "${0##*/}: info: fetching contract source from etherscan..." 33 | SRCDIR=$(TMPDIR=. mktemp -d seth.debug.XXXX -p /tmp) 34 | if seth bundle-source "$(<<< "$targetTx" seth --field to)" --dir "$SRCDIR" > "$SRCDIR"/standard.json ; then 35 | opts=(--source "$SRCDIR"/standard.json); 36 | else 37 | echo >&2 "${0##*/}: warning: no source available" 38 | fi 39 | fi 40 | 41 | index="$(<<< "$targetTx" seth --field transactionIndex)" 42 | block=$(seth block "$(<<< "$targetTx" seth --field blockNumber)" --full) 43 | txs=($(<<< "$block" seth --field transactions | seth --show-json)) 44 | timestamp="$(<<< "$block" seth --field timestamp)" 45 | 46 | j=0 47 | for i in "${txs[@]}"; do 48 | tx=$(<<< "$i" seth --show-json) 49 | hash=$(<<< "$tx" seth --field hash) 50 | 51 | if [[ "$1" = "$hash" ]]; then 52 | echo -e >&2 "\r${0##*/}: info: transaction ($j/$index)" 53 | seth run-tx "$hash" --state "$state" --debug "${opts[@]}" 54 | tidy 55 | break 56 | else 57 | [[ $SETH_VERBOSE ]] && 58 | echo -e >&2 "\r${0##*/}: info: transaction ($j/$index)" || 59 | echo -en >&2 "\r${0##*/}: info: transaction ($j/$index)" 60 | # exit code 2 means REVERT or otherwise acceptable failure 61 | seth run-tx "$hash" --state "$state" --timestamp "$timestamp" > /dev/null || 62 | [[ $? == 2 ]] || 63 | (tidy; echo ""; seth --fail "${0##*/}: error: hevm error while executing tx: $hash") 64 | j=$((j + 1)) 65 | fi 66 | done 67 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-estimate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-estimate -- estimate how much gas a transaction is likely to use 3 | ### Usage: seth estimate [] [] 4 | ### or: seth estimate [] 5 | ### or: seth estimate [] --create [] 6 | ### or: seth estimate [] --create 7 | ### 8 | ### Perform a local call to and return the gas usage. 9 | ### 10 | ### If has the form `()', infer from /. 11 | ### With `--create', estimate gas usage of creation of a new object. 12 | ### With `--create' and , encode constructor args into . 13 | ### 14 | ### With `-B ', use the state of the blockchain as of . 15 | ### With `-F ', simulate calling from 16 | ### With `-V ', simulate transferring to . 17 | set -e 18 | [[ $2 ]] || seth --fail-usage "$0" 19 | 20 | if [[ $SETH_CREATE ]]; then 21 | DATA=$(seth --to-hexdata "$1") 22 | if [[ $2 ]]; then 23 | args=$(seth calldata "${@:2}") 24 | args=${args#0x} 25 | DATA+=${args:8} 26 | fi 27 | else 28 | TO=$(seth --to-address "$1") 29 | DATA=$(seth calldata "${@:2}") 30 | fi 31 | 32 | jshon+=(-n {}) 33 | [[ $TO ]] && jshon+=(-s "$TO" -i to) 34 | jshon+=(-s "$DATA" -i data) 35 | # shellcheck disable=SC2207 36 | jshon+=($(SETH_PARAMS_NO_GAS=1 seth --send-params)) 37 | jshon+=(-i append) 38 | [[ $ETH_BLOCK = [0-9]* ]] && ETH_BLOCK=$(seth --to-hex "$ETH_BLOCK") 39 | : "${ETH_BLOCK:=latest}" # geth doesn't like this argument 40 | [[ $ETH_BLOCK = latest ]] || jshon+=(-s "$ETH_BLOCK" -i append) 41 | seth rpc eth_estimateGas -- "${jshon[@]}" 42 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-etherscan-source: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-etherscan-source -- fetch the contract source from etherscan 3 | ### Usage: seth etherscan-source
[] 4 | ### 5 | ### Requires an etherscan api key assigned to ETHERSCAN_API_KEY 6 | set -e 7 | [[ $ETHERSCAN_API_KEY ]] || { 8 | cat >&2 <<. 9 | 10 | You need an Etherscan Api Key to source contracts. 11 | Create one at https://etherscan.io/myapikey 12 | 13 | Then export it with \`export ETHERSCAN_API_KEY=xxxxxxxx' 14 | 15 | . 16 | exit 1 17 | } 18 | 19 | [[ -z "$1" ]] && seth --fail-usage 20 | 21 | ADDR=$(seth --to-address "$1") 22 | 23 | chain=$(seth chain) 24 | 25 | case "$chain" in 26 | ethlive|mainnet) 27 | URL="${ETHERSCAN_API_URL:-https://api.etherscan.io}" 28 | ;; 29 | ropsten|kovan|rinkeby|goerli) 30 | URL="${ETHERSCAN_API_URL:-https://api-$chain.etherscan.io}" 31 | ;; 32 | optimism-mainnet) 33 | URL="${ETHERSCAN_API_URL:-https://api-optimistic.etherscan.io}" 34 | ;; 35 | optimism-kovan) 36 | URL="${ETHERSCAN_API_URL:-https://api-kovan-optimistic.etherscan.io/}" 37 | ;; 38 | arbitrum-mainnet) 39 | URL="${ETHERSCAN_API_URL:-https://api.arbiscan.io}" 40 | ;; 41 | arbitrum-rinkeby) 42 | URL="${ETHERSCAN_API_URL:-https://api-testnet.arbiscan.io}" 43 | ;; 44 | bsctest) 45 | URL="${ETHERSCAN_API_URL:-https://api-testnet.bscscan.com}" 46 | ;; 47 | bsc) 48 | URL="${ETHERSCAN_API_URL:-https://api.bscscan.com}" 49 | ;; 50 | polygon) 51 | URL="${ETHERSCAN_API_URL:-https://api.polygonscan.com}" 52 | ;; 53 | polygon-mumbai) 54 | URL="${ETHERSCAN_API_URL:-https://api-testnet.polygonscan.com}" 55 | ;; 56 | fantom) 57 | URL="${ETHERSCAN_API_URL:-https://api.ftmscan.com}" 58 | ;; 59 | *) 60 | echo >&2 "Source fetching only works on mainnet, ropsten, kovan, rinkeby, goerli, optimism-mainnet, optimism-kovan, arbitrum-mainnet, polygon, and fantom." 61 | exit 1 62 | esac 63 | 64 | 65 | RESPONSE=$(seth curl "${URL}/api?module=contract&action=getsourcecode&address=${ADDR}&apikey=${ETHERSCAN_API_KEY}" | seth --show-json) 66 | 67 | MSG=$(echo "$RESPONSE" | seth --field message) 68 | 69 | ABI=$(echo "$RESPONSE" | seth --field result | jq '.[0].ABI' | seth --show-json) 70 | 71 | [[ $MSG == OK ]] || seth --fail "error: bad response: $MSG" 72 | 73 | 74 | if [[ $ABI == "Contract source code not verified" ]]; then 75 | seth --fail "$ABI" 76 | else 77 | echo "$RESPONSE" | seth --field result | jq '.[0]' 78 | fi 79 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-events: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-events -- print the decoded events of some contract 3 | ### Usage: seth events [-B ] [--follow]
4 | ### To use this command, you need to set the `SETH_ABI' variable: 5 | ### export SETH_ABI=$(seth abi 'event Foo(uint bar);') 6 | set -e -o pipefail 7 | [[ $1 ]] || seth --fail-usage "$0" 8 | seth logs "$@" | seth --decode-events 9 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-gas-price: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | seth rpc eth_gasPrice 4 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-get-block-by-hash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | seth rpc eth_getBlockByHash -- -s "$1" -i append -n false -i append 4 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-get-block-by-number: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | number=$1 4 | [[ $1 = latest ]] || number=$(seth --to-hex "$1") 5 | jshon+=(-s "$number" -i append) 6 | jshon+=(-n false -i append) 7 | seth rpc eth_getBlockByNumber -- "${jshon[@]}" 8 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-get-full-block-by-hash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | seth rpc eth_getBlockByHash -- -s "$1" -i append -n true -i append 4 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-get-full-block-by-number: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | number=$1 4 | [[ $1 = latest ]] || number=$(seth --to-hex "$1") 5 | jshon+=(-s "$number" -i append) 6 | jshon+=(-n true -i append) 7 | seth rpc eth_getBlockByNumber -- "${jshon[@]}" 8 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-get-tx-by-hash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | seth rpc eth_getTransactionByHash -- -s "$1" -i append 4 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-hashrate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | seth rpc eth_hashrate 4 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-help: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-help -- print help about seth(1) or one of its subcommands 3 | ### Usage: seth help [] 4 | ### or: seth --help 5 | 6 | BUGS=https://github.com/dapphub/dapptools/issues 7 | 8 | name=seth 9 | file=${0%-*}${1+-$1} 10 | header=$(perl -ne 'print "$2\n" if /^(\S)\1\1(?: (.*))?/' "$file") 11 | 12 | if ! [[ $header ]]; then 13 | sed "s/^/${0##*/}: /" "$file" 14 | elif [[ $(wc -l <<<"$header") = 1 ]]; then 15 | echo "$header" 16 | else 17 | sed "1{/^$name\\S* -- /d;}" <<<"$header" 18 | fi 19 | 20 | [[ $1 ]] && exit 21 | 22 | for file in "${0%/*}"/"$name"-*; do 23 | if [[ -L $file ]]; then 24 | continue 25 | elif [[ $file = */$name---* ]]; then 26 | special_commands+=("$file") 27 | else 28 | normal_commands+=("$file") 29 | fi 30 | done 31 | 32 | list-commands() { 33 | cat "$@" | 34 | perl -ne 'print "$2 $3\n" if /^(\S)\1\1 '"$name"'-(\S+) -- (.*)/' | 35 | while read -r name label; do 36 | printf " %-14s %s\\n" "$name" "$label" 37 | done | LANG=C sort 38 | } 39 | 40 | cat <<. 41 | 42 | Special commands: 43 | 44 | $(list-commands "${special_commands[@]}") 45 | 46 | Commands: 47 | 48 | $(list-commands "${normal_commands[@]}") 49 | 50 | Report bugs to <$BUGS>. 51 | . 52 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-index: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-index -- Prints the slot number for the specified mapping type and input data 3 | ### Usage: seth index [] 4 | ### 5 | ### Prints the slot number for the specified mapping type and input data. For example, 6 | ### the balances mapping in DAI is slot 2, so to find the slot where the balance 7 | ### is stored for , use 8 | ### seth-index address uint256 2 9 | ### 10 | ### `lang` will default to Solidity when not specified. To use Vyper, enter `v`, `vy`, 11 | ### or `vyper`. The above example cna be repeated for a Vyper token with 12 | ### seth-index address uint256 2 vyper 13 | 14 | set -e 15 | [[ $# -eq 4 ]] || [[ $# -eq 5 ]] || seth --fail-usage "$0" 16 | 17 | if [[ $5 = 'vyper' || $5 = 'vy' || $5 = 'v' ]]; then 18 | # note: not guaranteed to be accurate for all Vyper versions since storage layout is not yet stable 19 | # more info: https://twitter.com/big_tech_sux/status/1420159854170152963 20 | echo >&2 "${0##*/}: warning: not guaranteed to be accurate for all Vyper versions since storage layout is not yet stable" 21 | echo $(seth keccak $(seth abi-encode "x($2,$1)" $4 $3)); 22 | else 23 | echo $(seth keccak $(seth abi-encode "x($1,$2)" $3 $4)); 24 | fi 25 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-keccak: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /// seth-keccak -- print the Keccak hash of an arbitrary piece of data 3 | /// Usage: seth keccak [] 4 | /// 5 | /// Compute the keccak hash of , or stdin if not given. 6 | /// 7 | /// If has a 0x prefix, read it as hexdata. Multiple hexstrings 8 | /// can be concatenated with `:`. 9 | /// 10 | /// If has no 0x prefix, read it as text. 11 | 12 | var keccak256 = require('./sha3.js').keccak256; 13 | 14 | var data; 15 | if (process.argv.length < 3) { 16 | data = require("fs").readFileSync("/dev/stdin", { encoding: "utf-8" }) 17 | } else if (process.argv.length == 3) { 18 | data = process.argv[2]; 19 | } else { 20 | console.error("Usage: seth keccak []") 21 | process.exit(1) 22 | } 23 | 24 | if (data.startsWith('0x')) { 25 | data = data.replace(/(^0x|:0x)/g,'') 26 | if (/^[0-9a-fA-F]*$/.test(data)) { 27 | var res = keccak256(Buffer.from(data, 'hex')) 28 | console.log(`0x${res}`) 29 | } else { 30 | console.error("seth-keccak: error: invalid hexdata") 31 | process.exit(1) 32 | } 33 | } else { 34 | var res = keccak256(data) 35 | console.log(`0x${res}`) 36 | } 37 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-keccak-rpc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # seth-keccak -- print the Keccak hash of an arbitrary piece of data 3 | set -e 4 | [[ $# = 1 ]] || seth --fail-usage "$0" 5 | hexdata=$(seth --to-hexdata "$1") 6 | seth rpc web3_sha3 -- -s "$hexdata" -i append 7 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-listening: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | listening=$(seth rpc net_listening) 4 | [[ $listening = true ]] 5 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-logs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-logs -- print the transaction logs of some contract 3 | ### Usage: seth logs [-B ] [--follow]
[] [] 4 | set -e 5 | [[ $1 ]] || seth --fail-usage "$0" 6 | seth-logs-"${ETH_LOGS_API:-rpc}" \ 7 | "$(seth --to-address "$1")" \ 8 | "${ETH_BLOCK-earliest}" "$2" "$3" 9 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-logs-etherscan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | [[ $SETH_FOLLOW ]] && { 4 | echo >&2 "${0##*/}: error: \`--follow' not supported" 5 | exit 1 6 | } 7 | params=( 8 | "module=logs" "action=getLogs" 9 | "address=$1" "fromBlock=$2" "toBlock=latest" 10 | "apikey=$ETHERSCAN_API_KEY" 11 | ) 12 | [[ "$3" ]] && params[6]="topic0=$3" 13 | [[ "$4" ]] && params[7]="topic0_1_opr=and" 14 | [[ "$4" ]] && params[8]="topic1=$4" 15 | query=$(printf "&%s" "${params[@]}") 16 | response=$(seth curl "${ETHERSCAN_API_URL?}""${query/&/?}") 17 | message=$(jshon <<<"$response" -e message -u) 18 | result=$(jshon <<<"$response" -e result -j) 19 | if [[ $message = OK || $result = "[]" ]]; then 20 | jshon <<<"$result" -a -j 21 | else 22 | echo >&2 "${0##*/}: error: $response" 23 | exit 1 24 | fi 25 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-logs-follow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | seth rpc eth_getFilterChanges -- -s "$1" -i append 4 | sleep 1 5 | exec "$0" "$@" 6 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-logs-rpc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e -o pipefail 3 | jshon+=(-n {}) 4 | jshon+=(-s "$1" -i address) 5 | jshon+=(-s "$2" -i fromBlock) 6 | [[ "$3" ]] && jshon+=(-n []); jshon+=(-s "$3" -i append) 7 | [[ "$4" ]] && jshon+=(-s "$4" -i append) 8 | [[ "$3" ]] && jshon+=(-i topics) 9 | jshon+=(-i append) 10 | id=$(seth rpc eth_newFilter -- "${jshon[@]}") 11 | trap 'seth rpc eth_uninstallFilter -- -s "$id" -i append >/dev/null' EXIT 12 | seth rpc -j eth_getFilterLogs -- -s "$id" -i append | jshon -a -j 13 | [[ $SETH_FOLLOW ]] && seth logs-follow "$id" 14 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-lookup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | name=${ETH_ENV+${ETH_ENV}_}${1#@} 4 | name=$(tr "[:lower:]" "[:upper:]" <<<"$name") 5 | name=${name//-/_} 6 | [[ ${!name} ]] || seth --fail "${0##*/}: error: not found: \`$name'" 7 | echo "${!name}" 8 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-lookup-address: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-lookup-address -- returns the ENS name the provided address reverse resolves to 3 | ### Usage: seth lookup-address 4 | ### 5 | ### Print the ENS name the provided address reverse resolves to. If the name is 6 | ### not owned or does not have a resolver configured, an `invalid data for 7 | ### function output` error will be thrown. An error will also be thrown 8 | ### if the forward and reverse resolution do not match. 9 | 10 | set -e 11 | shopt -s extglob 12 | [[ $# -lt 2 ]] || seth --fail-usage "$0" 13 | 14 | # verify chain ID 15 | chainid=$(seth chain-id) 16 | if [[ $chainid != @(1|3|4|5) ]]; then 17 | seth --fail "${0##*/}: error: using chain ID $chainid, but ENS lookups are only supported for chain IDs 1, 3, 4, and 5" 18 | fi 19 | 20 | # get namehash for
.addr.reverse 21 | addressin=$(seth --to-hexdata $1) # make address lowercase 22 | namein=$(echo $addressin.addr.reverse | cut -c3-) 23 | namehash=0x$(seth namehash $namein | cut -c3-) 24 | 25 | # get name from the resolver 26 | ENS_REGISTRY=${SETH_ENS_REGISTRY:-'0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e'} # same on all supported networks 27 | resolver=$(seth call $ENS_REGISTRY "resolver(bytes32)(address)" $namehash) 28 | name=$(seth call $resolver "name(bytes32)(string)" $namehash) 29 | 30 | # check the reverse direction and make sure the addresses match 31 | address=$(seth resolve-name $name) 32 | if [[ $(seth --to-hexdata $address) != $addressin ]]; then 33 | seth --fail "${0##*/}: error: forward resolution of the found ENS name $name did not match" 34 | fi 35 | 36 | # success 37 | echo $name 38 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-ls: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-ls -- display a list of your local accounts and balances (in wei) 3 | set -e 4 | accounts=$(seth accounts | awk '{print $1}') 5 | for x in $accounts; do 6 | printf "%s\\t%s\\n" "$x" "$(seth balance "$x" || echo -)" & 7 | done | sort 8 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-mining: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | mining=$(seth rpc eth_mining) 4 | [[ $mining = true ]] 5 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-mktx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-mktx -- construct a signed transaction using ethsign 3 | ### Usage: seth mktx [] [-F ] [] 4 | ### or: seth mktx [] [-F ] 5 | set -e 6 | 7 | # shellcheck disable=SC2015 8 | [[ $# ]] && [[ $ETH_FROM ]] || seth --fail-usage "$0" 9 | 10 | value=$(seth --to-wei "${ETH_VALUE:-0}") 11 | value=$(seth --to-hex "$value") 12 | if [[ $2 ]]; then 13 | data=$(seth calldata "${@:2}") 14 | fi 15 | 16 | args=( 17 | --from "$(seth --to-address "$ETH_FROM")" 18 | --nonce "${ETH_NONCE:-$(seth nonce "$ETH_FROM")}" 19 | --chain-id "$(seth chain-id)" 20 | --gas-price "${ETH_GAS_PRICE:-$(seth gas-price)}" 21 | --gas-limit "${ETH_GAS:-200000}" 22 | --value "$value" 23 | --data "${data:-0x}" 24 | ) 25 | 26 | if [[ $SETH_CREATE ]]; then 27 | args+=(--create) 28 | else 29 | args+=(--to "$(seth --to-address "$1")") 30 | fi 31 | 32 | if [[ $ETH_PRIO_FEE ]]; then 33 | args+=(--prio-fee "$ETH_PRIO_FEE") 34 | fi 35 | 36 | if [ -n "$ETH_PASSWORD" ]; then args+=(--passphrase-file "$ETH_PASSWORD"); fi 37 | 38 | tx=$([[ $SETH_VERBOSE ]] && set -x; ethsign tx "${args[@]}") 39 | echo "$tx" 40 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-namehash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-namehash -- returns the ENS namehash of the provided name 3 | ### Usage: seth namehash 4 | ### 5 | ### Print the ENS namehash of the provided name 6 | 7 | set -e 8 | [[ $# -lt 2 ]] || seth --fail-usage "$0" 9 | 10 | # ENS namehash process is defined at https://docs.ens.domains/contract-api-reference/name-processing#hashing-names 11 | namehash() { 12 | if [[ $# == 0 ]]; then 13 | seth --to-bytes32 0 14 | else 15 | seth keccak $(namehash "${@:2}")$(seth keccak "$1" | cut -c3-) 16 | fi 17 | } 18 | 19 | namelower=$(echo $1 | tr "[:upper:]" "[:lower:]") # to lowercase 20 | name=${namelower//./ } # convert input from period delimited to space delimited 21 | namehash=$(namehash $name) 22 | echo $namehash 23 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-nonce: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-nonce -- show the number of transactions sent from an address 3 | ### Usage: seth nonce [-B ]
4 | ### Print the number of transactions sent from
. 5 | ### 6 | ### With `-B ', print the number of transactions as of . 7 | set -e 8 | [[ $# = 1 ]] || seth --fail-usage "$0" 9 | ADDRESS=$(seth --to-hexdata "$1") 10 | jshon+=(-s "$ADDRESS" -i append) 11 | jshon+=(-s "${ETH_BLOCK-latest}" -i append) 12 | seth rpc eth_getTransactionCount -- "${jshon[@]}" 13 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-publish: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-publish -- publish an already-signed transaction to the blockchain 3 | ### Usage: seth publish [] 4 | ### Publish a previously signed transaction to the blockchain. 5 | ### 6 | ### If no is given, read it from standard input instead. 7 | set -e 8 | txdata=$(seth --to-hexdata "$@") 9 | jshon+=(-s "$txdata" -i append) 10 | seth rpc eth_sendRawTransaction -- "${jshon[@]}" 11 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-receipt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-receipt -- wait for a transaction receipt to appear and print it 3 | ### Usage: seth receipt [--async] [] 4 | ### Print information about the transaction receipt for . 5 | ### If is given, print only that piece of information. 6 | ### If no is given, print the whole transaction receipt. 7 | ### Unless `--async' is given, wait indefinitely for the receipt to appear. 8 | set -e 9 | [[ $1 ]] || seth --fail-usage "$0" 10 | tx=$(seth --to-hexdata "$1") 11 | jshon+=(-s "$tx" -i append) 12 | receipt=$(seth rpc eth_getTransactionReceipt -- "${jshon[@]}") 13 | [[ $receipt != null ]] && number=$(seth --field <<<"$receipt" blockNumber) 14 | [[ ${number-null} != null && $2 ]] && exec seth --field "$2" <<<"$receipt" 15 | [[ ${number-null} != null ]] && exec echo "$receipt" 16 | [[ $SETH_ASYNC = yes ]] && seth --fail "${0##*/}: error: not found: $tx" 17 | sleep_seconds=1 18 | [[ $SETH_CHAIN ]] && sleep_seconds=5 19 | sleep "$sleep_seconds"; [[ $SETH_TICK ]] && printf . >&2 20 | exec "$0" "$@" 21 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-resolve-name: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-resolve-name -- returns the address the provided ENS name resolves to 3 | ### Usage: seth resolve-name 4 | ### 5 | ### Print the address the provided ENS name resolves to. If the name is not 6 | ### owned or does not have a resolver configured, an `invalid data for 7 | ### function output` error will be thrown 8 | 9 | set -e 10 | shopt -s extglob 11 | [[ $# -lt 2 ]] || seth --fail-usage "$0" 12 | 13 | # verify chain ID 14 | chainid=$(seth chain-id) 15 | if [[ $chainid != @(1|3|4|5) ]]; then 16 | seth --fail "${0##*/}: error: using chain ID $chainid, but ENS lookups are only supported for chain IDs 1, 3, 4, and 5" 17 | fi 18 | 19 | # get namehash 20 | namehash=$(seth namehash $1) 21 | 22 | # resolve name 23 | ENS_REGISTRY=${SETH_ENS_REGISTRY:-'0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e'} # same on all supported networks 24 | resolver=$(seth call $ENS_REGISTRY "resolver(bytes32)(address)" $namehash) 25 | address=$(seth call $resolver "addr(bytes32)(address)" $namehash) 26 | echo $address 27 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-rpc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | version=$(jshon --version) 5 | min=20131105 6 | if [[ $version -lt $min ]]; then 7 | echo >&2 "${0##*/}: error: jshon $version is too old (need $min or newer)" 8 | exit 1 9 | fi 10 | 11 | rpc-result() { jshon -Q -e result -j; } 12 | rpc-error() { jshon -Q -e error -j; } 13 | 14 | request=$(seth rpc-request -- "$@") 15 | response=$(seth rpc-curl <<<"$request") 16 | 17 | if result=$(rpc-result <<<"$response"); then 18 | seth --show-json <<<"$result" 19 | elif error=$(rpc-error <<<"$response"); then 20 | { echo "$request" 21 | SETH_KEY_WIDTH=10 seth --show-json <<<"$error" | sed 's/^/error: /' 22 | } | sed >&2 "s/^/${0##*/}: /" 23 | exit 1 24 | else 25 | echo >&2 "$response" 26 | exit 1 27 | fi 28 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-rpc-curl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | data=$(cat) 4 | seth curl "$ETH_RPC_URL" -- -d "$data" -H "Content-Type: application/json" || { 5 | code=$? 6 | [[ $code = 7 ]] && sed >&2 <<. "s/^/${0##*/}: /" 7 | Please make sure that you are running a local Ethereum node: 8 | For example, try running either \`parity' or \`geth --rpc'. 9 | You could also try connecting to an external Ethereum node: 10 | For example, try \`export ETH_RPC_URL=https://mainnet.infura.io'. 11 | If you have an Infura API key, add it to the end of the URL. 12 | . 13 | exit $code 14 | } 15 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-rpc-request: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | jshon <<<{} \ 4 | -s 2.0 \ 5 | -i jsonrpc \ 6 | -n 1 \ 7 | -i id \ 8 | -s "$1" \ 9 | -i method \ 10 | -n [] "${@:2}" \ 11 | -i params 12 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-run-tx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-run-tx -- execute a transaction using hevm 3 | ### Usage: seth run-tx [] 4 | ### or: seth run-tx [] 5 | ### 6 | ### Run a transaction with hevm in the environment of the given transaction. 7 | ### 8 | ### Attempts to fetch contract source from etherscan if `ETHERSCAN_API_KEY` is set. 9 | ### 10 | ### With `--state dir`, load and save state from `dir` 11 | ### With `--trace`, print the call trace of the transaction. 12 | ### With `--debug`, execute with hevm's interactive debugger 13 | ### With `--no-src`, do not attempt to fetch contract source from etherscan 14 | ### With `--source`, manually supply a solc compiler output json (implies --no-src) 15 | set -e 16 | 17 | # if the argument begins with 0x, we assume it to be a tx hash 18 | # otherwise, we assume that it contains the result of a seth tx call 19 | if [[ $1 = 0x* ]]; then 20 | tx=$(seth tx "$1") 21 | elif [[ $1 = blockHash* ]]; then 22 | tx=$1 23 | else 24 | seth --fail "${0##*/}: malformed transaction hash or data: $1" 25 | fi 26 | 27 | TO=$(<<< "$tx" seth --field to) 28 | DATA=$(<<< "$tx" seth --field input | seth --to-hex) 29 | if [[ "$TO" == 'null' ]]; then 30 | opts+=(--create --code "$DATA") 31 | else 32 | opts+=(--address "$TO" --calldata "$DATA") 33 | fi 34 | 35 | if [[ -n "$ETHERSCAN_API_KEY" && -z "$DAPP_JSON" && "$SETH_NOSRC" != yes ]]; then 36 | TMP=$(mktemp -d) 37 | DAPP_JSON="$TMP/solc.out.json" 38 | seth bundle-source --dir "$TMP" "$TO" > "$DAPP_JSON" || : 39 | fi 40 | 41 | opts+=(--caller "$(<<< "$tx" seth --field from)" ) 42 | opts+=(--origin "$(<<< "$tx" seth --field from)") 43 | opts+=(--value "$(<<< "$tx" seth --field value)") 44 | opts+=(--gas "$(<<< "$tx" seth --field gas)") 45 | opts+=(--nonce "$(<<< "$tx" seth --field nonce)") 46 | opts+=(--number "$(<<< "$tx" seth --field blockNumber)") 47 | opts+=(--block "$(("$(<<< "$tx" seth --field blockNumber)" - 1))") 48 | opts+=(--rpc "${ETH_RPC_URL}") 49 | opts+=(--timestamp "${HEVM_TIMESTAMP:-$(seth block "$(<<< "$tx" seth --field blockNumber)" timestamp)}") 50 | opts+=(--chainid "${ETH_CHAINID:-$(seth rpc eth_chainId | seth --to-dec)}") 51 | 52 | [[ "$HEVM_STATE" ]] && opts+=(--state "$HEVM_STATE") 53 | [[ "$HEVM_DEBUG" ]] && opts+=(--debug) 54 | [[ "$HEVM_TRACE" ]] && opts+=(--trace) 55 | [[ "$DAPP_JSON" ]] && opts+=(--json-file "$DAPP_JSON") 56 | 57 | ([[ $SETH_VERBOSE ]] && set -x; [[ $DAPP_JSON ]] && cd "$TMP"; hevm exec "${opts[@]}") 58 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-sig: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-sig -- print the 4-byte signature of a method 3 | ### Usage: seth sig 4 | ### Example: seth sig "withdraw(uint256)" 5 | ### Returns: 0x2e1a7d4d 6 | set -e 7 | [[ $# = 1 ]] || seth --fail-usage "$0" 8 | 9 | # Get ABI from input 10 | abi=$(seth --abi-function-json "$1") 11 | inputs=$(echo "$abi" | jq '.inputs[] | .type') 12 | 13 | # Generate dummy args 14 | args=() 15 | for input in $inputs; do 16 | type="${input//\"}" # remove leading and trailing quotes from the JSON 17 | end=${type: -1} # get the last character to check for array types 18 | if [[ "$end" = "]" ]]; then 19 | arg="[]" 20 | elif [[ "$type" =~ ^byte.*$ ]]; then 21 | arg="0x" 22 | elif [[ "$type" =~ ^string$ ]]; then 23 | arg='""' 24 | else 25 | arg=0 26 | fi 27 | args+=(--arg "$arg") 28 | done 29 | 30 | # Use dummy args generate calldata and only keep the function selector 31 | calldata=$(hevm abiencode --abi "$abi" "${args[@]}") 32 | echo "${calldata:0:10}" 33 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-sign: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-sign -- sign arbitrary data with one of your account keys 3 | ### Usage: seth sign [-F ] 4 | ### Sign with the private key of . 5 | set -e 6 | [[ $# = 1 ]] || seth --fail-usage "$0" 7 | [[ $ETH_FROM ]] || seth --fail "${0##*/}: error: \`ETH_FROM' not set" 8 | ethsign msg --data "$(seth --to-hexdata "$1")" --from "$ETH_FROM" 9 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-solc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-solc -- compile a single file using a default --standard-json input 3 | ### Usage: seth solc [] 4 | ### 5 | ### The following environment variables can be set: 6 | ### - DAPP_SOLC (default `solc`) 7 | ### - DAPP_SOLC_OPTIMIZE (default false) 8 | ### - DAPP_SOLC_OPTIMIZE_RUNS (default 200) 9 | ### - DAPP_SOLC_JSON (must be provided if not specified) 10 | ### 11 | ### You can pass --dir to control the directory in which compilation will occur (default cwd) 12 | ### 13 | set -e 14 | 15 | OPTIMIZE=${DAPP_SOLC_OPTIMIZE:-false} 16 | RUNS=${DAPP_SOLC_OPTIMIZE_RUNS:-200} 17 | SOLC=${DAPP_SOLC:-solc} 18 | SETH_DIR=${SETH_DIR:-.} 19 | 20 | if [[ -z "$DAPP_SOLC_JSON" && -z "$1" ]]; then 21 | seth --fail "must provide either .sol input file or DAPP_SOLC_JSON standard json" 22 | fi 23 | 24 | # default compiler settings, unless provided 25 | JSON="${DAPP_SOLC_JSON:-$(jq -n '{} 26 | | .language = "Solidity" 27 | | .sources[$src]["urls"] = [$src] 28 | | .settings.optimizer = 29 | if $optimize then {"enabled": $optimize, "runs": $runs} 30 | else {"enabled": $optimize} 31 | end 32 | ' --arg src "$1" --argjson optimize "$OPTIMIZE" --argjson runs "$RUNS")}" 33 | 34 | # regardless of the input we override the outputSelection to ensure 35 | # we have what hevm wants 36 | JSON="$(<<<"$JSON" jq '. 37 | | .settings.outputSelection["*"]["*"]=[ 38 | "metadata", 39 | "evm.bytecode", 40 | "evm.deployedBytecode", 41 | "abi", 42 | "storageLayout", 43 | "evm.bytecode.sourceMap", 44 | "evm.bytecode.linkReferences", 45 | "evm.bytecode.generatedSources", 46 | "evm.deployedBytecode.sourceMap", 47 | "evm.deployedBytecode.linkReferences", 48 | "evm.deployedBytecode.generatedSources", 49 | "evm.deployedBytecode.immutableReferences" 50 | ] 51 | | .settings.outputSelection["*"][""] = ["ast"] 52 | ')" 53 | 54 | ( [[ $SETH_VERBOSE ]] && set -x; 55 | cd "$SETH_DIR" && echo "$JSON" | $SOLC --standard-json --allow-paths "$(realpath "${1:-.}")" | jq . ) 56 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-storage: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-storage -- show the value of a storage slot on the blockchain 3 | ### Usage: seth storage [-B ]
4 | ### 5 | ### Print the value of a certain storage slot at a certain address. 6 | ### With `-B ', print the value as of that block. 7 | set -e 8 | [[ $# = 2 ]] || seth --fail-usage "$0" 9 | address=$(seth --to-address "$1") 10 | slot=$(seth --to-hex "$2") 11 | jshon+=(-s "$address" -i append) 12 | jshon+=(-s "$slot" -i append) 13 | jshon+=(-s "${ETH_BLOCK-latest}" -i append) 14 | seth rpc eth_getStorageAt -- "${jshon[@]}" 15 | -------------------------------------------------------------------------------- /src/seth/libexec/seth/seth-tx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### seth-tx -- print a table of information about a transaction 3 | ### Usage: seth tx [] 4 | ### Show information about the transaction . 5 | ### 6 | ### If is given, print only that piece of information. 7 | ### If no is given, show all the fields in a big table. 8 | set -e 9 | [[ $# = [12] ]] || seth --fail-usage "$0" 10 | tx=$(seth get-tx-by-hash "$1") 11 | [[ $tx = null ]] && seth --fail "${0##*/}: error: no such transaction: $1" 12 | [[ $2 ]] && exec seth --field "$2" <<<"$tx" 13 | echo "$tx" 14 | -------------------------------------------------------------------------------- /src/token/Makefile: -------------------------------------------------------------------------------- 1 | default: test 2 | server:; python -m SimpleHTTPServer 3 | 4 | SHELL = bash 5 | dirs = {bin,libexec} 6 | prefix ?= /usr/local 7 | 8 | dirs:; mkdir -p $(prefix)/$(dirs) 9 | files = $(shell ls -d $(dirs)/*) 10 | install:; cp -r -n $(dirs) $(prefix) 11 | link: uninstall dirs; for x in $(files); do \ 12 | ln -s `pwd`/$$x $(prefix)/$$x; done 13 | uninstall:; rm -rf $(addprefix $(prefix)/,$(files)) 14 | 15 | test:; ! grep '^#!/bin/sh' libexec/*/* && \ 16 | grep '^#!/usr/bin/env bash' libexec/*/* | \ 17 | cut -d: -f1 | xargs shellcheck 18 | 19 | .PHONY: default server dirs install link uninstall test 20 | -------------------------------------------------------------------------------- /src/token/README: -------------------------------------------------------------------------------- 1 | This is a simple utility for performing ERC20 operations. 2 | 3 | Usage: token [] [] 4 | or: token --help 5 | 6 | Commands: 7 | 8 | allowance print the amount one account can spend from another 9 | approve approve another account to spend your tokens 10 | balance print the token balance of an account 11 | help show help about token(1) or one of its subcommands 12 | permit sign (and submit) EIP2612 or DAI style permits 13 | supply print the total supply of a token 14 | transfer transfer tokens from one account to another 15 | 16 | Use `make install' to install token(1) into `/usr/local'. 17 | Use `make link' to link token(1) into `/usr/local' from this directory. 18 | 19 | This program depends on Seth (see https://github.com/dapphub/seth). 20 | 21 | Example usage: 22 | 23 | $ cat ~/.sethrc 24 | export KOVAN_MKR=0x4bb514a7f83fbb13c2b41448208e89fabbcfe2fb 25 | export KOVAN_MKR_DECIMALS=18 26 | export KOVAN_DANIEL=0x0101010101010101010101010101010101010101 27 | export KOVAN_KENNY=0x0202020202020202020202020202020202020202 28 | 29 | $ token supply @mkr 30 | 1000000.000000000000000000 31 | 32 | $ token balance @mkr @daniel 33 | 0.000000000123456789 34 | 35 | $ token allowance 36 | Usage: token allowance 37 | 38 | $ token allowance @mkr @kenny daniel 39 | 0.500000000000000000 40 | 41 | $ token transfer 42 | Usage: token transfer [] 43 | Note: must be an integer representing wei (or equivalent). 44 | 45 | $ ETH_FROM=@daniel token transfer @mkr @daniel 150000000000000000 @kenny 46 | seth-send: Published 200-byte transaction. 47 | seth-send: 0x7682289e7245623cddf9657a47dae1c11c00466881cb7f5f2a4c2db8acec1594 48 | seth-send: Waiting for transaction receipt............................. 49 | seth-send: Transaction included in block 1622448. 50 | seth-send: note: return value may be inaccurate 51 | true 52 | 53 | $ token balance @mkr @daniel 54 | 0.150000000123456789 55 | 56 | $ token allowance @mkr @kenny daniel 57 | 0.350000000000000000 58 | 59 | $ token permit @mkr @daniel --submit 60 | 61 | -------------------------------------------------------------------------------- /src/token/bin/token: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | PATH=${0%/*/*}/libexec/token:$PATH token "$@" 3 | -------------------------------------------------------------------------------- /src/token/default.nix: -------------------------------------------------------------------------------- 1 | { lib, stdenv, makeWrapper, coreutils, perl, seth, ethsign, glibcLocales }: 2 | 3 | stdenv.mkDerivation rec { 4 | name = "token-${version}"; 5 | version = "0.5.3"; 6 | src = ./.; 7 | 8 | nativeBuildInputs = [makeWrapper]; 9 | buildPhase = "true"; 10 | makeFlags = ["prefix=$(out)"]; 11 | 12 | postInstall = 13 | let 14 | path = lib.makeBinPath [ coreutils perl seth ethsign ]; 15 | in 16 | '' 17 | wrapProgram "$out/bin/token" \ 18 | --prefix PATH : ${path} \ 19 | ${lib.optionalString (glibcLocales != null) '' 20 | --set LOCALE_ARCHIVE ${glibcLocales}/lib/locale/locale-archive 21 | ''} 22 | ''; 23 | 24 | meta = { 25 | description = "Command-line tool for ERC20 tokens"; 26 | homepage = https://github.com/dapphub/src/token; 27 | license = lib.licenses.gpl3; 28 | inherit version; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /src/token/index.css: -------------------------------------------------------------------------------- 1 | * { margin: 0; } 2 | html { font: 20pt/1.3 sans-serif; } 3 | body { max-width: 30rem; padding: 0 1rem; margin: auto; } 4 | h1 { font: 1.4rem sans-serif; text-align: center; margin: 1.5rem; } 5 | p { margin: 1rem 0; } 6 | 7 | table { width: 100%; border-collapse: collapse; } 8 | th { text-align: right; } 9 | td, th { padding: .25rem .5rem; } 10 | 11 | .note { border: 1px solid gray; padding: 1rem 1.25rem; } 12 | .note h2 { font-size: 1rem; margin-bottom: .5rem; } 13 | -------------------------------------------------------------------------------- /src/token/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Token balance

5 |
6 | 7 | -------------------------------------------------------------------------------- /src/token/libexec/token/token: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### token -- command-line client for Ethereum tokens (ERC20) 3 | ### Usage: token [] [] 4 | ### or: token --help 5 | ### 6 | ### Easily do things with your Ethereum tokens. 7 | set -e 8 | [[ $2 = --help ]] && exec token-help "$1" 9 | [[ $2 = --usage ]] && { token-help "$1" >&2; exit 1; } 10 | token-"${1-help}" "${@:2}" 11 | -------------------------------------------------------------------------------- /src/token/libexec/token/token---format: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | decimals=$(seth --lookup "$1-decimals" 2>/dev/null) || decimals=18 4 | seth --to-fix "$decimals" "$2" 5 | -------------------------------------------------------------------------------- /src/token/libexec/token/token---help: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | token help 3 | -------------------------------------------------------------------------------- /src/token/libexec/token/token-allowance: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### token-allowance -- print how much one account can transfer from another 3 | ### Usage: token allowance 4 | set -e 5 | [ $# = 3 ] || token allowance --usage 6 | sig="allowance(address,address)(uint)" 7 | allowance=$(seth call "$1" "$sig" "$2" "$3") 8 | token --format "$1" "$allowance" 9 | -------------------------------------------------------------------------------- /src/token/libexec/token/token-approve: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### token-approve -- set how much one account can transfer from another 3 | ### Usage: token approve 4 | ### Note: must be an integer representing wei (or equivalent). 5 | set -e 6 | [ $# = 3 ] || token approve --usage 7 | sig="approve(address,uint)(bool)" 8 | seth send "$1" "$sig" "$2" "$3" 9 | -------------------------------------------------------------------------------- /src/token/libexec/token/token-balance: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### token-balance -- print the token balance of an account 3 | ### Usage: token balance 4 | set -e 5 | [ $# = 2 ] || token balance --usage 6 | sig="balanceOf(address)(uint)" 7 | balance=$(seth call "$1" "$sig" "$2") 8 | token --format "$1" "$balance" 9 | -------------------------------------------------------------------------------- /src/token/libexec/token/token-help: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | BUGS=https://github.com/dapphub/dapptools/issues/new 3 | 4 | name=${0##*/} name=${name%-help} 5 | file=${0%-*}${1+-$1} 6 | header=$(perl -ne 'print "$2\n" if /^(\S)\1\1(?: (.*))?/' "$file") 7 | 8 | if ! [[ $header ]]; then 9 | sed "s/^/${0##*/}: /" "$file" 10 | elif [[ $(wc -l <<<"$header") = 1 ]]; then 11 | echo "$header" 12 | else 13 | sed "1{/^$name\\S* -- /d;}" <<<"$header" 14 | fi 15 | 16 | [[ $1 ]] && exit 17 | 18 | for file in "${0%/*}"/"$name"-*; do 19 | [[ -L $file ]] && continue 20 | commands+=("$file") 21 | done 22 | 23 | list-commands() { 24 | cat "$@" | 25 | perl -ne 'print "$2 $3\n" if /^(\S)\1\1 '"$name"'-(\S+) -- (.*)/' | 26 | while read -r name label; do 27 | printf " %-14s %s\\n" "$name" "$label" 28 | done | LANG=C sort 29 | } 30 | 31 | cat <<. 32 | 33 | Commands: 34 | 35 | $(list-commands "${commands[@]}") 36 | 37 | Report bugs to <$BUGS>. 38 | . 39 | -------------------------------------------------------------------------------- /src/token/libexec/token/token-permit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### token-permit -- sign (and submit) EIP2612 or DAI style permits 3 | set -e 4 | display_usage() { 5 | echo "Usage: token permit [] [] [--submit]" 6 | } 7 | 8 | for i in "$@"; do 9 | case $i in 10 | --submit) 11 | SUBMIT=yes 12 | shift 13 | ;; 14 | *) 15 | shift 16 | set -- "$@" "$i" 17 | ;; 18 | esac 19 | done 20 | 21 | if [ $# -lt 2 ]; then 22 | display_usage 23 | exit 1 24 | fi 25 | 26 | TOKEN=$1 27 | SPENDER=$2 28 | 29 | EIP2612_TYPEHASH=$(seth keccak $(seth --from-ascii "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")) 30 | PERMIT_TYPEHASH=$(seth call $TOKEN "PERMIT_TYPEHASH()(bytes32)") 31 | 32 | if [ "$EIP2612_TYPEHASH" != "$PERMIT_TYPEHASH" ]; then 33 | DAI=yes 34 | fi 35 | 36 | if [ -z ${DAI+x} ]; then 37 | VALUE=$(seth --to-uint256 ${3:-$(seth --to-int256 -1)}) 38 | else 39 | VALUE=$(seth --to-uint256 ${3:-"1"}) 40 | fi 41 | 42 | if [ -z ${DEADLINE+x} ] && [ -z ${DAI+x} ]; then 43 | DEADLINE=${4:-$(seth --to-int256 -1)} 44 | elif [ -z ${DEADLINE+x} ]; then 45 | DEADLINE=${4:-$(seth --to-uint256 0)} 46 | fi 47 | 48 | if [ -z ${DOMAIN_SEPARATOR+x} ]; then 49 | DOMAIN_SEPARATOR=$(seth call $TOKEN "DOMAIN_SEPARATOR()(bytes32)") 50 | fi 51 | 52 | if [ -z ${NONCE+x} ]; then 53 | NONCE=$(seth call $TOKEN "nonces(address)(bytes32)" $ETH_FROM) 54 | fi 55 | 56 | PAYLOAD="$(seth --to-uint256 $ETH_FROM)$(seth --to-uint256 $SPENDER)" 57 | 58 | if [ "$DAI" == "yes" ]; then 59 | PAYLOAD="$PAYLOAD$NONCE$DEADLINE$VALUE" 60 | else 61 | PAYLOAD="$PAYLOAD$VALUE$NONCE$DEADLINE" 62 | fi 63 | 64 | MESSAGE=$(echo "$DOMAIN_SEPARATOR$(seth keccak "$PERMIT_TYPEHASH"$(echo "$PAYLOAD"|sed 's/0x//g'))"|sed 's/0x//g') 65 | 66 | OPTS="" 67 | if [ $ETH_PASSWORD ]; then 68 | OPTS="--passphrase-file $ETH_PASSWORD" 69 | fi 70 | 71 | 72 | SIG=$(ethsign msg $OPTS --no-prefix --data "0x1901$MESSAGE") 73 | SIG_V=$((0x$(echo "$SIG" | cut -c 131-132))) 74 | SIG_R=$(echo "$SIG" | cut -c 1-66) 75 | SIG_S="0x$(echo "$SIG" | cut -c 67-130)" 76 | 77 | if [ "$SUBMIT" == yes ] && [ -z ${DAI+x} ]; then 78 | seth send $TOKEN "permit(address, address, uint256, uint256, uint8, bytes32, bytes32)" $ETH_FROM $SPENDER $VALUE $DEADLINE $SIG_V $SIG_R $SIG_S 79 | elif [ "$SUBMIT" == yes ]; then 80 | seth send $TOKEN "permit(address, address, uint256, uint256, bool, uint8, bytes32, bytes32)" $ETH_FROM $SPENDER $NONCE $DEADLINE $VALUE $SIG_V $SIG_R $SIG_S 81 | else 82 | printf '{"permit": {"owner":"%s","spender":"%s","nonce":"%s", "expiry": "%s", "value": "%s", "v": "%s", "r": "%s", "s": "%s"}}\n' "$ETH_FROM" "$SPENDER" "$NONCE" "$DEADLINE" "$VALUE" $SIG_V $SIG_R $SIG_S 83 | fi 84 | -------------------------------------------------------------------------------- /src/token/libexec/token/token-supply: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### token-supply -- print the total supply of a token 3 | ### Usage: token supply 4 | set -e 5 | [ $# = 1 ] || token supply --usage 6 | supply=$(seth call "$1" "totalSupply()(uint)") 7 | token --format "$1" "$supply" 8 | -------------------------------------------------------------------------------- /src/token/libexec/token/token-transfer: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ### token-transfer -- transfer tokens to one account from another 3 | ### Usage: token transfer [] 4 | ### Perform a `transfer' or (if is given) `transferFrom' operation. 5 | set -e 6 | [ $# = 3 ] || [ $# = 4 ] || token transfer --usage 7 | if [ $# = 3 ]; then 8 | sig="transfer(address,uint)(bool)" 9 | seth send "$1" "$sig" "$2" "$3" 10 | else 11 | sig="transferFrom(address,address,uint)(bool)" 12 | seth send "$1" "$sig" "$4" "$2" "$3" 13 | fi 14 | -------------------------------------------------------------------------------- /src/upload-haskell-package: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # This script is used to upload Haskell packages to Hackage... 4 | # 5 | # Run with FLAGS=--publish after making sure the candidate looks fine. 6 | 7 | set -ex 8 | cd "$1" 9 | rm -rf dist/*.tar.gz dist/docs 10 | nix-shell --command "cabal haddock --builddir=dist/docs --haddock-for-hackage \ 11 | --haddock-option=--hyperlinked-source" 12 | cabal sdist 13 | cabal upload $FLAGS dist-newstyle/sdist/*.tar.gz 14 | cabal upload $FLAGS -d dist/docs/*-docs.tar.gz 15 | 16 | --------------------------------------------------------------------------------