├── .build ├── .k.rev ├── .kevm.rev └── concrete-rules.txt ├── .editorconfig ├── .gitignore ├── .gitmodules ├── .travis.yml ├── Dockerfile ├── Jenkinsfile ├── LICENSE.md ├── Makefile ├── README.md ├── bihu ├── Makefile ├── README.md ├── bihu-contracts-verification-report.pdf ├── collectToken-spec.ini ├── collectToken-spec.k ├── collectToken │ ├── KeyRewardPool.inlined.gist │ ├── KeyRewardPool.inlined.sol │ ├── KeyRewardPool.modified.inlined.bytes │ ├── KeyRewardPool.modified.inlined.evm │ ├── KeyRewardPool.modified.inlined.gist │ └── KeyRewardPool.modified.inlined.sol ├── forwardToHotWallet-spec.ini ├── forwardToHotWallet │ ├── WarmWallet.inlined.gist │ ├── WarmWallet.inlined.sol │ ├── WarmWallet.modified.inlined.bytes │ ├── WarmWallet.modified.inlined.evm │ ├── WarmWallet.modified.inlined.gist │ └── WarmWallet.modified.inlined.sol ├── module-tmpl.k ├── spec-tmpl.k └── verification.k ├── casper ├── Makefile ├── README.md ├── abstract-casper.k ├── abstract-semantics.k ├── casper-spec.ini ├── casper.k ├── casper.lll ├── module-tmpl.k ├── protocol-verification.md ├── real.k ├── reward-penalty-model.pdf ├── reward-penalty-model.tex ├── simple_casper.v.py ├── spec-tmpl.k └── verification.k ├── deposit ├── README.md ├── algorithm-correctness │ ├── README.md │ ├── deposit-spec.k │ ├── deposit-spec.k.out │ ├── deposit-symbolic.k │ ├── deposit.k │ ├── imap.k │ ├── imap.smt2 │ ├── run.sh │ ├── test.deposit │ └── test.deposit.out ├── bytecode-verification │ ├── .build │ │ ├── .kevm.rev │ │ └── concrete-rules.txt │ ├── Makefile │ ├── README.md │ ├── abstract-semantics.k │ ├── deposit-spec-full.ini │ ├── deposit-spec.ini │ ├── deposit-spec.ini.md │ ├── evm.smt2 │ ├── lemmas.k │ ├── module-tmpl.k │ ├── spec-tmpl.k │ └── verification.k ├── deposit-formal-verification.pdf └── formal-incremental-merkle-tree-algorithm.pdf ├── erc20 ├── .build │ ├── .kevm.rev │ └── concrete-rules.txt ├── README.md ├── all │ ├── contracts │ │ ├── 01_tether.sol │ │ ├── 02_bnb.sol │ │ ├── 03_bitfinex.sol │ │ ├── 04_chainlink.sol │ │ ├── 05_huobi.sol │ │ ├── 06_maker.sol │ │ ├── 07_usdc.sol │ │ ├── 08_crypto.sol │ │ ├── 09_ino.sol │ │ ├── 10_bat.sol │ │ ├── 11_insight.sol │ │ ├── 12_paxos.sol │ │ ├── 13_hedg.sol │ │ ├── 14_zrx.sol │ │ ├── 15.1_vechain.sol │ │ ├── 15.2_trueusd.sol │ │ ├── 17_holo.sol │ │ ├── 18_omisego.sol │ │ ├── 20_centrality.sol │ │ ├── 21_bytom.sol │ │ ├── 22_kucoin.sol │ │ ├── 23_ekt.sol │ │ ├── 24_synthetix.sol │ │ ├── 25_reputation.sol │ │ ├── 26_theta.sol │ │ ├── 27_swipe.sol │ │ ├── 28_dai.sol │ │ ├── 29_icon.sol │ │ ├── 30_karat.sol │ │ ├── 31_mixin.sol │ │ ├── 33_ios.sol │ │ ├── 34_quant.sol │ │ ├── 35_mco.sol │ │ ├── 36_aeternity.sol │ │ ├── 39_nexo.sol │ │ ├── 40_clipper.sol │ │ ├── 41_rlc.sol │ │ ├── 44_noah.sol │ │ ├── 45_kyber.sol │ │ ├── 46_BitMax.sol │ │ ├── 47_DxChain.sol │ │ ├── 48_matic.sol │ │ ├── 49_snt.sol │ │ ├── 51_cryptoindex.sol │ │ ├── 52_banker.sol │ │ ├── 53_golem.sol │ │ ├── 54_mana.sol │ │ ├── 55_elf.sol │ │ ├── 56_aion.sol │ │ ├── 57_republic.sol │ │ └── code review.md │ ├── demo-specs │ │ ├── Makefile │ │ ├── certora-buggy.ini │ │ ├── certora-fixed.ini │ │ ├── consensys.ini │ │ ├── hkg.ini │ │ ├── hobby.ini │ │ ├── vyper.ini │ │ ├── zeppelin-new.ini │ │ └── zeppelin.ini │ ├── fragments-solar │ │ ├── allowance.ini │ │ ├── approve.ini │ │ ├── balanceOf.ini │ │ ├── root.ini │ │ ├── totalSupply.ini │ │ ├── transfer.ini │ │ └── transferFrom.ini │ ├── fragments │ │ ├── allowance.ini │ │ ├── approve.ini │ │ ├── balanceOf.ini │ │ ├── root.ini │ │ ├── totalSupply.ini │ │ ├── transfer.ini │ │ └── transferFrom.ini │ ├── mainnet-solar-specs │ │ ├── 01_tether.ini.disable │ │ ├── 02_bnb.ini │ │ ├── 04_chainlink.ini │ │ ├── 05_huobi.ini │ │ ├── 06_maker.ini │ │ ├── 08_crypto.ini │ │ ├── 09_ino.ini │ │ ├── 10_bat.ini │ │ ├── 11_insight.ini │ │ ├── 13_hedg.ini │ │ ├── 14_zrx.ini │ │ └── Makefile │ ├── mainnet-solar-test │ │ ├── 14_zrx.ini │ │ └── Makefile │ ├── mainnet-specs │ │ ├── 01_tether.ini.disable │ │ ├── 02_bnb.ini │ │ ├── 04_chainlink.ini │ │ ├── 05_huobi.ini │ │ ├── 06_maker.ini │ │ ├── 08_crypto.ini │ │ ├── 09_ino.ini │ │ ├── 10_bat.ini │ │ ├── 11_insight.ini │ │ ├── 13_hedg.ini │ │ ├── 14_zrx.ini │ │ └── Makefile │ ├── mainnet-test │ │ ├── 14_zrx.ini │ │ └── Makefile │ └── resources │ │ ├── get-bytecode.py │ │ ├── kprove-erc20-group.mak │ │ ├── kprove-erc20-solar.mak │ │ ├── kprove-erc20.mak │ │ └── spec-tmpl.k ├── ds-token │ ├── Makefile │ ├── README.md │ ├── base.sol │ ├── ds-token-erc20-spec.ini │ ├── spec-diff.patch │ ├── token.bytes │ ├── token.evm │ └── token.sol ├── evm-data-map-symbolic.k ├── gno │ ├── Makefile │ ├── README.md │ ├── gno-erc20-spec.ini │ ├── gno-erc20.bytes │ ├── program.k │ └── spec-tmpl.k ├── hkg │ ├── Makefile │ ├── README.md │ ├── StandardToken.inlined.buggy.sol │ ├── StandardToken.inlined.bytes │ ├── StandardToken.inlined.evm │ ├── StandardToken.inlined.gist │ ├── StandardToken.inlined.json │ ├── StandardToken.inlined.sol │ ├── hkg-erc20-spec.ini │ └── spec-diff.patch ├── hobby │ ├── Makefile │ ├── MyKidsEducationToken.buggy.sol │ ├── MyKidsEducationToken.fixed.bytes │ ├── MyKidsEducationToken.fixed.evm │ ├── MyKidsEducationToken.fixed.gist │ ├── MyKidsEducationToken.fixed.sol │ ├── README.md │ ├── hobby-erc20-spec.ini │ └── spec-diff.patch ├── module-tmpl.k ├── resources-concrete │ └── verification.k ├── solar │ ├── Makefile │ ├── module-tmpl.k │ ├── solar-abstract-semantics.k │ ├── solar-erc20-spec.ini │ ├── spec-tmpl.k │ └── verification-solar.k ├── spec-tmpl.k ├── verification.k ├── vyper │ ├── .build │ │ └── .kevm.rev │ ├── ERC20.v.bytes │ ├── ERC20.v.evm │ ├── ERC20.v.py │ ├── Makefile │ ├── README.md │ ├── lemmas-buf.md │ ├── module-tmpl.k │ ├── spec-tmpl.k │ ├── vyper-erc20-spec.ini │ └── vyper-verification.k └── zeppelin │ ├── Makefile │ ├── README.md │ ├── StandardToken.inlined.bytes │ ├── StandardToken.inlined.evm │ ├── StandardToken.inlined.gist │ ├── StandardToken.inlined.sol │ ├── spec-diff.patch │ └── zeppelin-erc20-spec.ini ├── gnosis ├── .build │ └── .kevm.rev ├── GnosisSafe_RuntimeVerification.pdf ├── GnosisSafe_RuntimeVerification_Audit.pdf ├── Makefile ├── abstract-semantics-segmented-gas.k ├── abstract-semantics.k ├── bmc │ ├── Makefile │ ├── generated-external-contract │ │ ├── ExternalContract.sol │ │ └── gnosis-testing-ExternalContract.hex │ └── gnosis-bmc-spec.ini ├── evm.smt2 ├── generated │ ├── Proxy.evm │ ├── gnosis-GnosisSafe-0.1.0.evm │ ├── gnosis-GnosisSafe-0.1.0.hex │ ├── gnosis-GnosisSafe-program-cell.txt │ ├── gnosis-Proxy-0.1.0.hex │ ├── rv-GnosisSafe-0.1.0-solc-0.5.1.evm │ ├── rv-GnosisSafe-0.1.0-solc-0.5.1.hex │ └── solidity compilation instructions.txt ├── gnosis-spec.ini ├── module-tmpl.k ├── old │ ├── PROPOSAL.md │ ├── issues.md │ ├── old-issues.md │ └── pseudo-spec.md ├── scripts │ └── hex_to_decimal.py ├── spec-tmpl.k ├── test │ ├── ApiTest.hex │ ├── ApiTest.sol │ ├── Makefile │ └── api-test-spec.ini └── verification.k ├── k-test ├── KTest.sol ├── Makefile ├── abstract-semantics.k ├── k-test-spec.ini ├── smt-prelude.smt2 ├── spec-tmpl.k └── verification.k ├── proxied-token ├── Makefile ├── README.md ├── deployed.sol ├── module-tmpl.k ├── proxied-token-spec.ini ├── spec-tmpl.k └── verification.k ├── resources ├── Makefile ├── abstract-semantics-direct-gas.k ├── abstract-semantics-segmented-gas.k ├── balanceOf-spec.k ├── build-html.sh ├── debugging.md ├── ecrec-symbolic.k ├── edsl-notations.md ├── edsl-spec.md ├── edsl.md ├── erc20-evm.md ├── evm-data-map-concrete.k ├── evm-data-map-symbolic.k ├── evm-direct-gas.k ├── evm-symbolic.k ├── evm.smt2 ├── gen-spec.py ├── instructions.md ├── kprove-group.mak ├── kprove-tutorial.md ├── kprove.mak ├── lemmas-buf.md ├── lemmas.md ├── not-KLabel.k ├── pdf-icon.png ├── relink.lua └── sum-to-n.md ├── run-proofs.sh ├── script ├── dkprove.sh └── kprove_log.py └── uniswap ├── .build └── .kevm.rev ├── Makefile ├── README.md ├── abstract-semantics.k ├── code ├── bytes.txt ├── lll.txt └── uniswap_exchange.vy ├── issues.md ├── lemmas.md ├── module-tmpl.k ├── results ├── README.md ├── addLiquidity-1.txt ├── addLiquidity-2.txt ├── ethToTokenSwapInput.txt ├── ethToTokenSwapOutput.txt └── removeLiquidity.txt ├── spec-tmpl.k ├── uniswap-spec.ini ├── verification.k └── x-y-k.pdf /.build/.k.rev: -------------------------------------------------------------------------------- 1 | a61af7e96e94e83485ada3f5ebaf22277f972cbb 2 | -------------------------------------------------------------------------------- /.build/.kevm.rev: -------------------------------------------------------------------------------- 1 | 004de7f6ef8b8509f033ef846fc81517c4980134 2 | -------------------------------------------------------------------------------- /.build/concrete-rules.txt: -------------------------------------------------------------------------------- 1 | EDSL.#ceil32 2 | EDSL.keccakIntList 3 | EVM-TYPES.#signed.positive 4 | EVM-TYPES.#signed.negative 5 | EVM-TYPES.#unsigned.positive 6 | EVM-TYPES.#unsigned.negative 7 | EVM-TYPES.powmod.nonzero 8 | EVM-TYPES.powmod.zero 9 | EVM-TYPES.signextend.invalid 10 | EVM-TYPES.signextend.negative 11 | EVM-TYPES.signextend.positive 12 | SERIALIZATION.keccak 13 | EVM-TYPES.#take.zero-pad 14 | EVM-TYPES.#asWord.recursive 15 | EVM-TYPES.#asByteStack 16 | EVM-TYPES.#asByteStackAux.recursive 17 | EVM-TYPES.#padToWidth 18 | EVM-TYPES.#padRightToWidth 19 | SERIALIZATION.#newAddr 20 | SERIALIZATION.#newAddrCreate2 21 | EVM-TYPES.mapWriteBytes.recursive 22 | EVM-TYPES.#range 23 | EVM-TYPES.#lookup.some 24 | EVM-TYPES.#lookup.none 25 | EVM.#memoryUsageUpdate.some 26 | EVM.Cgascap 27 | EVM.Csstore.new 28 | EVM.Csstore.old 29 | EVM.Rsstore.new 30 | EVM.Rsstore.old 31 | EVM.Cextra 32 | EVM.Cmem 33 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Root-level editorconfig. 2 | root = true 3 | 4 | # Applies to every file: 5 | # - make sure newlines are unix-stile 6 | # - remove whitespace at the end of lines 7 | [*] 8 | end_of_line = lf 9 | trim_trailing_whitespace = true 10 | 11 | # Applies to ini, k, md and smt2 files: 12 | # - indent using 4 spaces 13 | [*.{ini,k,md,smt2}] 14 | indent_style = space 15 | indent_size = 4 16 | 17 | [*.{patch,diff}] 18 | trim_trailing_whitespace = false 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | /.build/* 4 | !/.build/pandoc-tangle 5 | 6 | /specs/* 7 | 8 | *.html 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule ".build/pandoc-tangle"] 2 | path = .build/pandoc-tangle 3 | url = https://github.com/ehildenb/pandoc-tangle 4 | ignore = untracked 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | 3 | before_install: 4 | - wget https://github.com/jgm/pandoc/releases/download/2.1.1/pandoc-2.1.1-1-amd64.deb 5 | - sudo dpkg -i pandoc-2.1.1-1-amd64.deb 6 | - pandoc --version 7 | - wget https://github.com/Z3Prover/z3/releases/download/z3-4.6.0/z3-4.6.0-x64-ubuntu-14.04.zip 8 | - unzip z3-4.6.0-x64-ubuntu-14.04.zip 9 | - export PATH=$PATH:$PWD/z3-4.6.0-x64-ubuntu-14.04/bin 10 | - z3 --version 11 | - nproc 12 | - cat /proc/meminfo 13 | - export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi) 14 | - echo ${BRANCH#travis-test-} 15 | - export EXT_KPROVE_OPTS=--log-progress 16 | # - export K_OPTS=-Xmx6g 17 | # - travis_wait 30 sleep 1800 & 18 | 19 | language: java 20 | script: make all test MODE=${BRANCH#travis-test-} 21 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:bionic 2 | 3 | ENV TZ=America/Chicago 4 | RUN ln --symbolic --no-dereference --force /usr/share/zoneinfo/$TZ /etc/localtime \ 5 | && echo $TZ > /etc/timezone 6 | 7 | RUN apt update \ 8 | && apt upgrade --yes \ 9 | && apt install --yes \ 10 | autoconf bison build-essential clang++-6.0 clang-6.0 cmake coreutils \ 11 | curl diffutils flex gcc git gnupg libboost-test-dev libffi-dev \ 12 | libgmp-dev libjemalloc-dev libmpfr-dev libstdc++6 libtool libxml2 \ 13 | libyaml-cpp-dev llvm-6.0 m4 make maven opam openjdk-8-jdk pandoc \ 14 | pkg-config python3 python-jinja2 python-pygments python-recommonmark \ 15 | python-sphinx scala time unifdef zlib1g-dev 16 | 17 | RUN update-alternatives --set java /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java 18 | 19 | RUN curl -sSL https://get.haskellstack.org/ | sh 20 | 21 | RUN git clone 'https://github.com/z3prover/z3' --branch=z3-4.6.0 \ 22 | && cd z3 \ 23 | && python scripts/mk_make.py \ 24 | && cd build \ 25 | && make -j8 \ 26 | && make install \ 27 | && cd ../.. \ 28 | && rm -rf z3 29 | 30 | ARG USER_ID=1000 31 | ARG GROUP_ID=1000 32 | RUN groupadd --gid $GROUP_ID user \ 33 | && useradd --create-home --uid $USER_ID --shell /bin/sh --gid user user 34 | 35 | USER $USER_ID:$GROUP_ID 36 | 37 | RUN cd /home/user \ 38 | && git clone 'https://github.com/kframework/k' --branch=nightly-0f3835d3a \ 39 | && ./k/k-distribution/src/main/scripts/bin/k-configure-opam-dev \ 40 | && rm -rf k 41 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # Reproducibility License 1.1.0 2 | 3 | ## Acceptance 4 | 5 | In order to get any license under these terms, you must 6 | agree to their rules. Those rules are both obligations 7 | under your agreement and conditions to all your licenses. 8 | 9 | ## Reproducibility 10 | 11 | These terms license you _only_ for the following purposes: 12 | 13 | 1. You may reproduce published research results that the 14 | licensor achieved using this software. 15 | 16 | 2. You may produce and reproduce research results of your 17 | own, and of others, only for noncommercial purposes. 18 | 19 | These terms do _not_ license you for any other purpose, 20 | such as producing or reproducing new research results for 21 | commercial purposes. 22 | 23 | ## Copyright 24 | 25 | The licensor grants you a copyright license for 26 | the software. That license covers everything you 27 | might do with the software that would infringe the 28 | licensor's copyright in it, for the purposes permitted 29 | in [Reproducibility](#reproducibility). That license 30 | does _not_ cover making changes or new work based on the 31 | software or removing this license from the software. 32 | 33 | ## Patent 34 | 35 | The licensor grants you a patent license for the software. 36 | That license covers patent claims the licensor can 37 | license, or becomes able to license, that you would have to 38 | infringe to use the software for the purposes permitted in 39 | [Reproducibility](#reproducibility). That license does 40 | _not_ cover selling the software. 41 | 42 | ## Patent Defense 43 | 44 | If you or any affiliated company makes any written claim 45 | alleging that the software infringes or contributes to 46 | infringement of a patent, your patent license under these 47 | terms ends immediately. 48 | 49 | ## No Other Rights 50 | 51 | These terms do not allow you to sublicense or transfer 52 | any licenses to anyone else, or prevent the licensor from 53 | granting licenses to anyone else. These terms do not 54 | imply any other licenses. 55 | 56 | ## Reliability 57 | 58 | The licensor may not revoke any license under these terms. 59 | 60 | ## No Liability 61 | 62 | ***As far as the law allows, this software comes as is, 63 | without any warranty or condition, and the licensor will 64 | not be liable to anyone for any damages related to this 65 | software or this license, under any kind of legal claim.*** 66 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .NOTPARALLEL: 2 | 3 | MINIMAL_DIRS:= resources erc20/vyper erc20/zeppelin 4 | KTEST_DIRS:= k-test 5 | ERC20_DIRS:= erc20/hkg erc20/hobby erc20/ds-token 6 | SOLAR_DIRS:= erc20/solar 7 | DEPOSIT_DIRS:= deposit/bytecode-verification 8 | GNOSIS_DIRS:= gnosis gnosis/test 9 | GNOSIS_BMC_DIRS:=gnosis/bmc 10 | BIHU_DIRS:= bihu 11 | DOM_DIRS:= erc20/gno proxied-token 12 | # fails - needs updates in verification.k 13 | CASPER_DIRS:= casper 14 | # fails - has to get rid of custom lemmas.md 15 | UNISWAP_DIRS:= uniswap 16 | 17 | JENKINS_DIRS:=$(MINIMAL_DIRS) $(KTEST_DIRS) $(ERC20_DIRS) $(GNOSIS_DIRS) $(BIHU_DIRS) 18 | ALL_DIRS:= $(JENKINS_DIRS) $(DEPOSIT_DIRS) $(GNOSIS_BMC_DIRS) $(DOM_DIRS) $(CASPER_DIRS) $(UNISWAP_DIRS) 19 | 20 | # For MODE=foo, SUBDIRS will be FOO_DIRS 21 | SUBDIRS:=$($(shell echo $(MODE) | tr a-z A-Z)_DIRS) 22 | 23 | include resources/kprove-group.mak 24 | -------------------------------------------------------------------------------- /bihu/Makefile: -------------------------------------------------------------------------------- 1 | #BUILD_DIR:=../erc20/.build 2 | 3 | SPEC_INI:=forwardToHotWallet-spec.ini 4 | 5 | SPEC_NAMES:=collectToken \ 6 | forwardToHotWallet-success-1 \ 7 | forwardToHotWallet-success-2 \ 8 | forwardToHotWallet-failure-1 \ 9 | forwardToHotWallet-failure-2 \ 10 | forwardToHotWallet-failure-3 \ 11 | forwardToHotWallet-failure-4 12 | 13 | include ../resources/kprove.mak 14 | 15 | COLLECTION_TOKEN_INI:=collectToken-spec.ini 16 | 17 | # non-standard spec generation 18 | $(SPECS_DIR)/$(SPEC_GROUP)/collectToken-spec.k: $(TMPLS) $(COLLECTION_TOKEN_INI) $(LEMMAS) 19 | python3 $(RESOURCES)/gen-spec.py $(TMPLS) $(COLLECTION_TOKEN_INI) collectToken collectToken loop ds-math-mul > $@ 20 | -------------------------------------------------------------------------------- /bihu/bihu-contracts-verification-report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/verified-smart-contracts/e61ef57de99d07d7182436490f152a14621c5a82/bihu/bihu-contracts-verification-report.pdf -------------------------------------------------------------------------------- /bihu/collectToken/KeyRewardPool.inlined.gist: -------------------------------------------------------------------------------- 1 | https://gist.github.com/anonymous/08052033a247f241c9519e41d6fcd27d 2 | -------------------------------------------------------------------------------- /bihu/collectToken/KeyRewardPool.modified.inlined.bytes: -------------------------------------------------------------------------------- 1 | 0x60606040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630e4aed3f1461007257806340ba126b1461009b578063787e9137146100db578063b69ef8a814610104578063b93e2cdb1461012d575b600080fd5b341561007d57600080fd5b610085610171565b6040518082815260200191505060405180910390f35b34156100a657600080fd5b6100c56004808035906020019091908035906020019091905050610176565b6040518082815260200191505060405180910390f35b34156100e657600080fd5b6100ee6101a8565b6040518082815260200191505060405180910390f35b341561010f57600080fd5b6101176101ae565b6040518082815260200191505060405180910390f35b341561013857600080fd5b61015760048080359060200190919080359060200190919050506101b4565b604051808215151515815260200191505060405180910390f35b600a81565b600081831061019d576301e1338061018e84846102bc565b81151561019757fe5b046101a0565b60005b905092915050565b60005481565b60015481565b600080600080600080600080888a1115156101ce57600080fd5b6101dc6000546001546102d5565b96508695506101eb8a8a610176565b9450600093505b848410156102215761021261020b87600a6064036102ee565b606461031c565b955083806001019450506101f2565b61023661022f87600a6102ee565b606461031c565b9250610260610256846301e133808c8e0381151561025057fe5b066102ee565b6301e1338061031c565b915085870382019050610275816000546102bc565b90506001548111156102875760015490505b610293600054826102d5565b6000819055506102a5600154826102bc565b600181905550600197505050505050505092915050565b600082828403915081111515156102cf57fe5b92915050565b600082828401915081101515156102e857fe5b92915050565b60008183029050600083148061030e575081838281151561030b57fe5b04145b151561031657fe5b92915050565b6000818381151561032957fe5b049050929150505600a165627a7a72305820d8edeeb44c8346eca139385cfaecddeb8b02fcc380c3b54473746e8103ff62e70029 2 | -------------------------------------------------------------------------------- /bihu/collectToken/KeyRewardPool.modified.inlined.gist: -------------------------------------------------------------------------------- 1 | https://gist.github.com/anonymous/61b969d0f7af252a54f48f4b50f2c3f5 2 | -------------------------------------------------------------------------------- /bihu/forwardToHotWallet/WarmWallet.inlined.gist: -------------------------------------------------------------------------------- 1 | https://gist.github.com/anonymous/c95f67810dff2af73b240c78aab4e3b9 2 | -------------------------------------------------------------------------------- /bihu/forwardToHotWallet/WarmWallet.modified.inlined.gist: -------------------------------------------------------------------------------- 1 | https://gist.github.com/anonymous/b7773008aa9dc75815f1c6ecfb7224a0 2 | -------------------------------------------------------------------------------- /bihu/module-tmpl.k: -------------------------------------------------------------------------------- 1 | requires "abstract-semantics-direct-gas.k" 2 | requires "verification.k" 3 | 4 | module {MODULE}-SPEC 5 | imports ABSTRACT-SEMANTICS-DIRECT-GAS 6 | imports VERIFICATION 7 | 8 | {RULES} 9 | 10 | endmodule 11 | -------------------------------------------------------------------------------- /bihu/spec-tmpl.k: -------------------------------------------------------------------------------- 1 | // {RULENAME} 2 | rule 3 | {K} 4 | 1 5 | NORMAL 6 | BYZANTIUM 7 | 8 | 9 | 10 | {OUTPUT} 11 | {STATUSCODE} 12 | _ => _ 13 | _ 14 | _ => _ 15 | 16 | 17 | #parseByteStack({CODE}) 18 | #computeValidJumpDests(#parseByteStack({CODE})) 19 | 20 | ACCT_ID // contract owner 21 | CALLER_ID // who called this contract; in the begining, origin // msg.sender 22 | 23 | {CALLDATA} 24 | 25 | 0 26 | {WORDSTACK} 27 | {LOCALMEM} 28 | {PC} 29 | {GAS} 30 | {MEMORYUSED} 31 | _ => _ 32 | 33 | false // NOTE: non-static call 34 | CALL_DEPTH 35 | 36 | 37 | 38 | _ 39 | {LOG} 40 | {REFUND} // TODO: more detail 41 | 42 | 43 | _ 44 | ORIGIN_ID // who fires tx 45 | _ 46 | 47 | _ 48 | _ 49 | _ 50 | _ 51 | _ 52 | _ 53 | _ 54 | _ 55 | _ 56 | _ 57 | _ 58 | NOW // block.timestamp // now 59 | _ 60 | _ 61 | _ 62 | 63 | _ 64 | 65 | 66 | 67 | 68 | 0 69 | SetItem(ACCT_ID) _:Set 70 | 71 | 72 | 73 | ACCT_ID 74 | _ 75 | #parseByteStack({CODE}) 76 | 77 | {STORAGE} 78 | 79 | _ 80 | _ 81 | 82 | // ... // TODO: fix 83 | 84 | 85 | _ 86 | _ 87 | _ 88 | 89 | 90 | requires 0 <=Int ACCT_ID andBool ACCT_ID LT W0 W1 => bool2Word(W0 #push ... [trusted] 5 | 6 | rule GT W0 W1 => bool2Word(W0 >Int W1) ~> #push ... [trusted] 7 | 8 | rule EQ W0 W1 => bool2Word(W0 ==Int W1) ~> #push ... [trusted] 9 | 10 | rule ISZERO W => bool2Word(W ==Int 0 ) ~> #push ... [trusted] 11 | 12 | rule SLT W0 W1 => W0 s #push ... [trusted] 13 | rule SGT W0 W1 => W1 s #push ... [trusted]*/ 14 | 15 | rule #gasExec(SCHED, EXP W0 W1) => Gexp < SCHED > +Int (Gexpbyte < SCHED > *Int 32) ... 16 | requires W1 =/=K 0 [trusted] 17 | 18 | rule #gasExec(SCHED, SSTORE INDEX VALUE) => Gsstoreset < SCHED > ... [trusted] 19 | 20 | rule Ccallgas(SCHED, ISEMPTY:Bool, GCAP, GAVAIL, 0) => Cgascap(SCHED, GCAP, GAVAIL, Cextra(SCHED, 0, ISEMPTY)) ... [trusted] 21 | 22 | rule Ccallgas(SCHED, ISEMPTY:Bool, GCAP, GAVAIL, VALUE) 23 | => Cgascap(SCHED, GCAP, GAVAIL, Cextra(SCHED, VALUE, ISEMPTY)) +Int Gcallstipend < SCHED > ... 24 | requires VALUE =/=Int 0 [trusted] 25 | 26 | endmodule 27 | -------------------------------------------------------------------------------- /casper/module-tmpl.k: -------------------------------------------------------------------------------- 1 | requires "abstract-semantics.k" 2 | requires "verification.k" 3 | 4 | module {MODULE}-SPEC 5 | imports ABSTRACT-SEMANTICS 6 | imports VERIFICATION 7 | 8 | {RULES} 9 | 10 | endmodule 11 | -------------------------------------------------------------------------------- /casper/real.k: -------------------------------------------------------------------------------- 1 | requires "domains.k" 2 | 3 | module REAL-SYNTAX 4 | syntax Real [hook(REAL.Real)] 5 | syntax Real ::= r"[\\+-]?[0-9]+\\.[0-9]+" [prefer, token, prec(2)] // [token, prec(1)] 6 | endmodule 7 | 8 | module REAL 9 | imports REAL-SYNTAX 10 | imports BOOL 11 | imports INT-SYNTAX 12 | 13 | syntax Real ::= "--Real" Real [function, smtlib(-), hook(REAL.neg)] 14 | > Real "^Real" Real [function, left, hook(REAL.pow)] 15 | > left: 16 | Real "*Real" Real [function, left, smtlib(*), hook(REAL.mul)] 17 | | Real "/Real" Real [function, left, smtlib(div), hook(REAL.div)] 18 | > left: 19 | Real "+Real" Real [function, left, smtlib(+), hook(REAL.add)] 20 | | Real "-Real" Real [function, left, smtlib(-), hook(REAL.sub)] 21 | 22 | syntax Bool ::= Real "<=Real" Real [function, left, smtlib(<=), hook(REAL.le)] 23 | | Real "=Real" Real [function, left, smtlib(>=), hook(REAL.ge)] 25 | | Real ">Real" Real [function, left, smtlib(>), hook(REAL.gt)] 26 | | Real "==Real" Real [function, left, smtlib(==), hook(REAL.eq), klabel(_==Real_)] 27 | | Real "=/=Real" Real [function, left, smtlib((not (== #1 #2)))] 28 | 29 | rule F1:Real =/=Real F2:Real => notBool (F1 ==Real F2) 30 | 31 | syntax Real ::= rootReal(Real, Int) [function, hook(REAL.root)] 32 | | sqrtReal(Real) [function] 33 | | absReal(Real) [function, smtlib(abs), hook(REAL.abs)] 34 | | floorReal(Real) [function, hook(REAL.floor)] 35 | | ceilReal(Real) [function, hook(REAL.ceil)] 36 | | expReal(Real) [function, hook(REAL.exp)] 37 | | logReal(Real) [function, hook(REAL.log)] 38 | | sinReal(Real) [function, hook(REAL.sin)] 39 | | cosReal(Real) [function, hook(REAL.cos)] 40 | | tanReal(Real) [function, hook(REAL.tan)] 41 | | asinReal(Real) [function, hook(REAL.asin)] 42 | | acosReal(Real) [function, hook(REAL.acos)] 43 | | atanReal(Real) [function, hook(REAL.atan)] 44 | | atan2Real(Real, Real) [function, hook(REAL.atan2)] 45 | | maxReal(Real, Real) [function, smtlib(max), hook(REAL.max)] 46 | | minReal(Real, Real) [function, smtlib(min), hook(REAL.min)] 47 | 48 | rule sqrtReal(R:Real) => rootReal(R, 2) 49 | 50 | syntax Real ::= Int2Real(Int) [function, hook(REAL.int2real)] 51 | syntax Int ::= Real2Int(Real) [function, hook(REAL.real2int)] 52 | 53 | endmodule 54 | 55 | -------------------------------------------------------------------------------- /casper/reward-penalty-model.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/verified-smart-contracts/e61ef57de99d07d7182436490f152a14621c5a82/casper/reward-penalty-model.pdf -------------------------------------------------------------------------------- /casper/reward-penalty-model.tex: -------------------------------------------------------------------------------- 1 | \section{Reward-Penalty Model} 2 | 3 | Let $V \in \V$ be a validator. 4 | Let $D^V_i$ be the deposit (in \t{ether}) of $V$ in epoch $i$. 5 | Let $\D_i \defeq \Sigma_{V \in \V} D^V_i$ be the total amount of deposits (in \t{ether}) in epoch $i$. 6 | Let $\RF_i$ be a reward-penalty factor in epoch $i$. 7 | 8 | In each epoch $i$, validator $V$ gets reward and/or penalty as follows. 9 | \lst{ 10 | \i $V$ pays a fee for each epoch whether or not he votes. 11 | \i $V$ gets a reward, if he votes ``correctly'' --- the source epoch of the vote is equal to the recommended one. 12 | \i $V$ gets another reward, if epoch $i-1$ is finalized at the end of epoch $i$. 13 | } 14 | Given $D^V_i$ and $\RF_i$, $D^V_{i+1}$ is defined for each case as follows. 15 | Note that ``incorrect vote'' entails ``no vote''. 16 | \[ 17 | D^V_{i+1} \defeq 18 | \begin{cases} 19 | D^V_i \cdot \dfrac{1}{1 + \RF_i} & \m{if $V$ does \emph{not} vote (correctly), and epoch $i-1$ is \emph{not} finalized} 20 | \\[11pt] D^V_i \cdot \dfrac{1}{1 + \RF_i} \cdot (1 + \dfrac{\alpha}{2} \RF_i) & \m{if $V$ does \emph{not} vote (correctly), but epoch $i-1$ is finalized} 21 | \\[11pt] D^V_i \cdot \dfrac{1}{1 + \RF_i} \cdot (1 + \RF_i) & \m{if $V$ votes correctly, but epoch $i-1$ is \emph{not} finalized} 22 | \\[11pt] D^V_i \cdot \dfrac{1}{1 + \RF_i} \cdot (1 + \RF_i) \cdot (1 + \dfrac{\alpha}{2} \RF_i) & \m{if $V$ votes correctly, and epoch $i-1$ is finalized} 23 | \end{cases} 24 | \] 25 | Here, $\alpha$ is the fraction of the correct votes in the total deposit $\D_i$. 26 | Since $\alpha$ is used only when epoch $i-1$ is finalized (which implies the current epoch $i$ is justified), 27 | we have $\frac{2}{3} \le \alpha \le 1$. 28 | 29 | At the beginning of the next epoch $i+1$, 30 | the reward factor $\RF_{i+1}$ is also adjusted based on the current total deposit and the history of finalization as follows: 31 | \[ 32 | \RF_{i+1} \defeq \dfrac{\beta}{\sqrt{\D_{i}}} + \gamma \cdot (\ESF - 2) 33 | \] 34 | where $\beta$ is a fixed base interest factor, 35 | and $\gamma$ is a fixed base penalty factor. 36 | \ESF is the number of epochs since the last finalized epoch. 37 | We have $\ESF \ge 2$, 38 | at the beginning of epoch $i+1$, 39 | since the latest possible finalized epoch is $i-1$. 40 | 41 | \begin{lemma} 42 | We have the followings: 43 | \lst{ 44 | \i If $V$ votes correctly, his deposit \emph{never} decrease, i.e., $D^V_{i+1} \ge D^V_{i}$. 45 | \i If $V$ does not votes correctly (or does not vote at all), his deposit strictly decreases, i.e., $D^V_{i+1} < D^V_i$. 46 | \i In an ideal situation (all validators vote correctly and every epoch is finalized), 47 | each validator's deposit strictly increases for each epoch, i.e., $D^V_{i+1} > D^V_{i}$, 48 | and the reward factor strictly decreases for each epoch, i.e., $\RF_{i+1} < \RF_i$. 49 | % where the rate of increase is reduced, i.e., 50 | % \[ 51 | % 0 ~<~ D^V_{i+2} - D^V_{i+1} ~<~ D^V_{i+1} - D^V_{i} ~\le~ \frac{D^V_i \cdot \RF_i}{2} 52 | % \] 53 | \i The above holds for both positive and negative $\gamma$. 54 | } 55 | \end{lemma} 56 | 57 | \paragraph{Relationship to the contract source code} 58 | 59 | In the \verb|initialize_epoch| function\footnote{\url{https://github.com/ethereum/casper/blob/b2a1189506710c37bbdbbf3dc79ff383dbe13875/casper/contracts/simple_casper.v.py}}: 60 | \begin{itemize} 61 | \i $D^V_{i+1} \times 10^{18} \simeq \t{self.validators[$V$].deposit} \times \verb|self.deposit_scale_factor[epoch]|$ at line 273. 62 | \i $R_{i+1} \simeq \verb|self.reward_factor|$ at line 284. 63 | \i $i + 1 = \t{epoch}$ at line 266. 64 | \i $\sqrt{\D_{i}} \simeq \verb|self.sqrt_of_total_deposits()|$ at line 276. 65 | \i \ESF = \t{self.esp()} at line 277. 66 | \i $\alpha \simeq \verb|vote_frac|$ at line 231 of the \verb|collective_reward| function (called at line 270). 67 | \i $\beta$ = \verb|self.BASE_INTEREST_FACTOR| 68 | \i $\gamma$ = \verb|self.BASE_PENALTY_FACTOR| 69 | \end{itemize} 70 | -------------------------------------------------------------------------------- /casper/spec-tmpl.k: -------------------------------------------------------------------------------- 1 | // {RULENAME} {COMMENT} 2 | rule 3 | {K} 4 | 1 5 | NORMAL 6 | BYZANTIUM 7 | 8 | 9 | {OUTPUT} 10 | {STATUSCODE} 11 | {CALLSTACK} 12 | _ 13 | _ => _ 14 | 15 | #parseByteStack({CODE}) 16 | #computeValidJumpDests(#parseByteStack({CODE})) 17 | 18 | CASPER_ACCT_ID // this 19 | CALLER_ID // msg.sender 20 | {CALLDATA} // msg.data 21 | {CALLVALUE} // msg.value 22 | {WORDSTACK} 23 | {LOCALMEM} 24 | {PC} 25 | {GAS} 26 | {MEMORYUSED} 27 | _ => _ 28 | false // NOTE: non-static call 29 | {CALLDEPTH} 30 | 31 | 32 | _ 33 | {LOG} 34 | {REFUND} 35 | 36 | _ 37 | ORIGIN_ID // tx.origin 38 | BLOCK_HASHES // block.blockhash 39 | 40 | _ 41 | _ 42 | {COINBASE} // block.coinbase 43 | _ 44 | _ 45 | _ 46 | _ 47 | _ 48 | BLOCK_NUM // block.number 49 | _ 50 | _ 51 | NOW // now = block.timestamp 52 | _ 53 | _ 54 | _ 55 | _ 56 | 57 | 58 | 59 | {ACTIVEACCOUNTS} 60 | 61 | 62 | CASPER_ACCT_ID 63 | {CASPERBALANCE} 64 | #parseByteStack({CODE}) 65 | 66 | {STORAGE} 67 | 68 | _ 69 | _ 70 | 71 | {ACCOUNTS} 72 | ... 73 | 74 | _ 75 | _ 76 | _ 77 | 78 | 79 | requires #rangeAddress(CASPER_ACCT_ID) 80 | andBool #rangeAddress(CALLER_ID) 81 | andBool #rangeAddress(ORIGIN_ID) 82 | andBool #rangeUInt(256, NOW) 83 | // andBool #rangeUInt(128, BLOCK_NUM) // Solidity 84 | andBool #range(0 <= BLOCK_NUM <= maxSInt128) // Vyper (for now) 85 | // Account address normality 86 | andBool CASPER_ACCT_ID >Int 0 andBool (notBool CASPER_ACCT_ID in #precompiledAccounts(BYZANTIUM)) 87 | {REQUIRES} 88 | {ENSURES} 89 | {ATTRIBUTE} 90 | -------------------------------------------------------------------------------- /deposit/README.md: -------------------------------------------------------------------------------- 1 | _**[DEPRECATED: The result in this directory is outdated. The deposit contract has been reimplemented in Solidity and reverified. The latest result can be found at https://github.com/runtimeverification/deposit-contract-verification.]**_ 2 | 3 | *2020-01-21* 4 | 5 | # End-to-End Formal Verification of Ethereum 2.0 Deposit Contract _(Vyper Implementation)_ 6 | 7 | This directory provides the result of our end-to-end formal verification of the Ethereum 2.0 [deposit contract]. 8 | 9 | Documents: 10 | * Final report: [`deposit-formal-verification.pdf`](deposit-formal-verification.pdf) 11 | * Blog post: https://runtimeverification.com/blog/end-to-end-formal-verification-of-ethereum-2-0-deposit-smart-contract/ 12 | 13 | Verification artifacts: 14 | * [`algorithm-correctness/`](algorithm-correctness): Formalization and correctness proof of incremental Merkle tree algorithm 15 | * [`bytecode-verification/`](bytecode-verification): Bytecode verification of the deposit contract 16 | 17 | ## [Resources](/README.md#resources) 18 | 19 | ## [Disclaimer](/README.md#disclaimer) 20 | 21 | [deposit contract]: 22 | -------------------------------------------------------------------------------- /deposit/algorithm-correctness/README.md: -------------------------------------------------------------------------------- 1 | _**[DEPRECATED: The result in this directory is outdated. The deposit contract has been reimplemented in Solidity and reverified. The latest result can be found at https://github.com/runtimeverification/deposit-contract-verification.]**_ 2 | 3 | # Formalization and Correctness Proof of Incremental Merkle Tree Algorithm of Deposit Contract 4 | 5 | This directory presents our formalization of the [incremental Merkle tree algorithm], especially the one employed in the [deposit contract], and prove its correctness w.r.t. the [original full-construction Merkle tree algorithm]. 6 | 7 | Documents: 8 | * [Formalization of the incremental Merkle tree algorithm and its correctness proof](../formal-incremental-merkle-tree-algorithm.pdf) 9 | * [Blog post](https://runtimeverification.com/blog/formal-verification-of-ethereum-2-0-deposit-contract-part-1) 10 | 11 | Mechanized specifications and proofs in K: 12 | * [deposit.k](deposit.k): Formal model of the incremental Merkle tree algorithm 13 | * [deposit-spec.k](deposit-spec.k): Correctness specifications 14 | * [deposit-symbolic.k](deposit-symbolic.k): Lemmas (trusted) 15 | 16 | To prove the specifications: 17 | ``` 18 | $ ./run.sh 19 | ``` 20 | Prerequisites: 21 | * Install K: https://github.com/kframework/k/releases 22 | 23 | ## [Resources](/README.md#resources) 24 | 25 | ## [Disclaimer](/README.md#disclaimer) 26 | 27 | [deposit contract]: 28 | [incremental Merkle tree algorithm]: 29 | [original full-construction Merkle tree algorithm]: 30 | -------------------------------------------------------------------------------- /deposit/algorithm-correctness/deposit-spec.k: -------------------------------------------------------------------------------- 1 | require "deposit-symbolic.k" 2 | 3 | module DEPOSIT-SPEC 4 | 5 | imports DEPOSIT-SYMBOLIC 6 | 7 | // Lemma 7 (deposit). 8 | 9 | rule deposit(V) => . ... 10 | M => M +Int 1 11 | TREE_HEIGHT 12 | Branch1 => Branch2 13 | requires V ==Int tn(M +Int 1, 0, M +Int 1) 14 | andBool M =Int 1 17 | andBool isValidBranch(Branch1, M) 18 | ensures isValidBranch(Branch2, M +Int 1) 19 | 20 | rule depositLoop(I, TREE_HEIGHT -Int 1, down(I, M), tn(M, I, down(I, M))) => . ... 21 | M // M = m + 1 22 | TREE_HEIGHT 23 | Branch1 => Branch2 24 | requires I <=Int TREE_HEIGHT -Int 1 25 | andBool (2 ^Int I) *Int down(I, M) ==Int M 26 | andBool 1 <=Int M andBool M =Int 1 29 | andBool isValidBranch(Branch1, M -Int 1) 30 | ensures isValidBranch(Branch2, M) 31 | 32 | // Lemma 9 (get_deposit_root). 33 | 34 | rule getDepositRoot => tn(M, TREE_HEIGHT, 1) ... 35 | M 36 | TREE_HEIGHT 37 | Branch 38 | Zeros 39 | requires M getDepositRootLoop(K, TREE_HEIGHT, down(K, M), tn(M, K, up(K, M +Int 1))) => tn(M, TREE_HEIGHT, 1) ... 45 | M 46 | TREE_HEIGHT 47 | Branch 48 | Zeros 49 | requires K <=Int TREE_HEIGHT 50 | andBool M V requires K0 ==Int K 12 | rule M [ K0 <- V ] [ K ] => M [ K ] requires K0 =/=Int K 13 | // rule .IMap [ _ ] => 0 14 | 15 | // syntax IntMap 16 | // rule isInt( M:Map [ _ ] ) => isIntMap(M) 17 | // rule isInt( M:Map [ _ <- V:Int ] ) => isIntMap(M) 18 | endmodule 19 | 20 | module IMAP 21 | imports IMAP-SYNTAX 22 | imports IMAP-SYMBOLIC 23 | endmodule 24 | -------------------------------------------------------------------------------- /deposit/algorithm-correctness/imap.smt2: -------------------------------------------------------------------------------- 1 | (define-sort IMap () (Array Int Int)) 2 | -------------------------------------------------------------------------------- /deposit/algorithm-correctness/run.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | # concrete test 4 | rm -rf deposit-test 5 | kompile --backend java -d deposit-test deposit.k 6 | krun --smt none -cTREEHEIGHT=3 -d deposit-test test.deposit | diff - test.deposit.out 7 | 8 | # proof 9 | rm -rf deposit-symbolic-kompiled 10 | kompile --backend java deposit-symbolic.k --syntax-module DEPOSIT-SYMBOLIC 11 | kprove deposit-spec.k --smt-prelude imap.smt2 | diff - deposit-spec.k.out 12 | # kprove deposit-spec.k --smt-prelude imap.smt2 -v --debug --log --log-rules --debug-z3-queries --log-cells k,depositCount,branch,zerohashes,#pc,#result >/tmp/x 2>&1 13 | -------------------------------------------------------------------------------- /deposit/algorithm-correctness/test.deposit: -------------------------------------------------------------------------------- 1 | deposit 1 2 | deposit 2 3 | deposit 3 4 | deposit 4 5 | deposit 5 6 | deposit 6 7 | deposit 7 8 | //deposit 8 9 | getDepositRoot 10 | -------------------------------------------------------------------------------- /deposit/algorithm-correctness/test.deposit.out: -------------------------------------------------------------------------------- 1 | 2 | 3 | hash ( hash ( hash ( 1 , 2 ) , hash ( 3 , 4 ) ) , hash ( hash ( 5 , 6 ) , hash ( 7 , 0 ) ) ) 4 | 5 | 6 | .IMap [ 0 <- 0 ] [ 1 <- 0 ] [ 2 <- 0 ] [ 1 <- hash ( 0 , 0 ) ] [ 2 <- hash ( hash ( 0 , 0 ) , hash ( 0 , 0 ) ) ] 7 | 8 | 9 | .IMap [ 0 <- 0 ] [ 1 <- 0 ] [ 2 <- 0 ] [ 0 <- 1 ] [ 1 <- hash ( 1 , 2 ) ] [ 0 <- 3 ] [ 2 <- hash ( hash ( 1 , 2 ) , hash ( 3 , 4 ) ) ] [ 0 <- 5 ] [ 1 <- hash ( 5 , 6 ) ] [ 0 <- 7 ] 10 | 11 | 12 | 7 13 | 14 | 15 | 3 16 | 17 | 18 | -------------------------------------------------------------------------------- /deposit/bytecode-verification/.build/.kevm.rev: -------------------------------------------------------------------------------- 1 | 652576cb753656da51a25cea754d38c3d59470cd 2 | -------------------------------------------------------------------------------- /deposit/bytecode-verification/.build/concrete-rules.txt: -------------------------------------------------------------------------------- 1 | EDSL.#ceil32 2 | EDSL.keccakIntList 3 | EVM-DATA.#signed.positive 4 | EVM-DATA.#signed.negative 5 | EVM-DATA.#unsigned.positive 6 | EVM-DATA.#unsigned.negative 7 | EVM-DATA.powmod.nonzero 8 | EVM-DATA.powmod.zero 9 | EVM-DATA.signextend.invalid 10 | EVM-DATA.signextend.negative 11 | EVM-DATA.signextend.positive 12 | EVM-DATA.keccak 13 | EVM-DATA.#take.zero-pad 14 | EVM-DATA.#asWord.recursive 15 | EVM-DATA.#asByteStack 16 | EVM-DATA.#asByteStackAux.recursive 17 | EVM-DATA.#padToWidth 18 | EVM-DATA.#padRightToWidth 19 | EVM-DATA.#newAddr 20 | EVM-DATA.#newAddrCreate2 21 | EVM-DATA.mapWriteBytes.recursive 22 | EVM-DATA.#range 23 | EVM-DATA.#lookup.some 24 | EVM-DATA.#lookup.none 25 | EVM.#memoryUsageUpdate.some 26 | EVM.Cgascap 27 | EVM.Csstore.new 28 | EVM.Csstore.old 29 | EVM.Rsstore.new 30 | EVM.Rsstore.old 31 | EVM.Cextra 32 | EVM.Cmem 33 | -------------------------------------------------------------------------------- /deposit/bytecode-verification/Makefile: -------------------------------------------------------------------------------- 1 | KEVM_VERSION_FILE:=.build/.kevm.rev 2 | 3 | LOCAL_LEMMAS:=verification.k \ 4 | abstract-semantics.k \ 5 | lemmas.k 6 | TMPLS:=module-tmpl.k spec-tmpl.k 7 | 8 | SPEC_GROUP:=deposit 9 | SPEC_INI:=deposit-spec.ini 10 | 11 | KPROVE_OPTS:=--smt-prelude $(abspath $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/evm.smt2) \ 12 | --branching-allowed 0 \ 13 | --z3-cnstr-timeout 100 14 | 15 | SPEC_NAMES:= 16 | 17 | SPEC_NAMES += init-success 18 | SPEC_NAMES += init-revert 19 | 20 | SPEC_NAMES += get_deposit_root-success-init-then 21 | SPEC_NAMES += get_deposit_root-success-init-else 22 | SPEC_NAMES += get_deposit_root-success-loop-enter-then 23 | SPEC_NAMES += get_deposit_root-success-loop-enter-else 24 | SPEC_NAMES += get_deposit_root-success-loop-exit 25 | SPEC_NAMES += get_deposit_root-revert 26 | 27 | SPEC_NAMES += get_deposit_count-success 28 | SPEC_NAMES += get_deposit_count-revert 29 | 30 | SPEC_NAMES += deposit-success-data 31 | SPEC_NAMES += deposit-success-insert-init-then 32 | SPEC_NAMES += deposit-success-insert-init-else 33 | SPEC_NAMES += deposit-success-insert-loop-enter-then 34 | SPEC_NAMES += deposit-success-insert-loop-enter-else 35 | SPEC_NAMES += deposit-success-insert-loop-exit 36 | 37 | SPEC_NAMES += deposit-revert-1 38 | SPEC_NAMES += deposit-revert-2 39 | SPEC_NAMES += deposit-revert-3 40 | 41 | SPEC_NAMES += deposit-calldata-decoding-success 42 | SPEC_NAMES += deposit-calldata-decoding-revert-1 43 | SPEC_NAMES += deposit-calldata-decoding-revert-2 44 | SPEC_NAMES += deposit-calldata-decoding-revert-3 45 | SPEC_NAMES += deposit-calldata-decoding-revert-4 46 | SPEC_NAMES += deposit-calldata-decoding-revert-5 47 | SPEC_NAMES += deposit-calldata-decoding-revert-6 48 | 49 | SPEC_NAMES += revert-invalid_function_identifier-lt_4 50 | SPEC_NAMES += revert-invalid_function_identifier-ge_4-lt_32 51 | SPEC_NAMES += revert-invalid_function_identifier-ge_4-ge_32 52 | 53 | export K_OPTS=-Xmx16g 54 | 55 | include ../../resources/kprove.mak 56 | -------------------------------------------------------------------------------- /deposit/bytecode-verification/abstract-semantics.k: -------------------------------------------------------------------------------- 1 | requires "verification.k" 2 | 3 | module ABSTRACT-SEMANTICS 4 | imports VERIFICATION 5 | 6 | // to avoid unnecessary case analyses 7 | rule LT W0 W1 => bool2Word(W0 #push ... [trusted] 8 | rule GT W0 W1 => bool2Word(W0 >Int W1) ~> #push ... [trusted] 9 | rule EQ W0 W1 => bool2Word(W0 ==Int W1) ~> #push ... [trusted] 10 | rule ISZERO W => bool2Word(W ==Int 0 ) ~> #push ... [trusted] 11 | 12 | rule SHA256 => #end EVMC_SUCCESS ... 13 | DATA 14 | _ => #buf(32, #sha256(DATA)) 15 | requires notBool #isConcrete(DATA) 16 | [trusted] 17 | 18 | // gas abstraction 19 | 20 | // see also verification.k 21 | 22 | rule G':Int ~> #deductGas => . ... 23 | G => G -Gas G' 24 | requires notBool (#isConcrete(G) andBool #isConcrete(G')) 25 | [trusted] 26 | 27 | rule MU':Int ~> #deductMemory => . ... 28 | #symGas(_, _, _, _, CMEM => Cmem(SCHED, MU')) 29 | MU => MU' 30 | SCHED 31 | requires CMEM ==Int Cmem(SCHED, MU) 32 | [trusted, matching(#symGas)] 33 | 34 | rule GCALL:Int ~> #allocateCallGas => . ... 35 | _ => #symGas(GCALL, 0, 0, .List, 0) 36 | [trusted] 37 | 38 | rule #refund G:Int => . ... 39 | GAVAIL => GAVAIL +Gas G 40 | [trusted] 41 | 42 | /* NOTE: 43 | These abstractions are over-approximation, except that out-of-gas exceptions are ignored. 44 | The out-of-gas exception is not harmful when it comes to safety properties, and it can be avoided by simply providing enough gas. 45 | The only problematic case is to call sub-functions with a specific amount of gas (instead of all available gas at that point). 46 | In this case, additional analyses need to be made to ensure that the specific amount of gas is sufficient, for liveness properties. 47 | See the lemmas over `+Gas` for the analysis, which checks the remaining (i.e., refuned) gas is positive when returning to the caller. 48 | 49 | In particular, the deposit contract involves precompiled contract calls (i.e., SHA256 and ID), where ID calls are fed a specific amount of gas. 50 | That is, the amount of gas provided to ID calls is "18 + floor(CALLDATASIZE / 10)", 51 | which is greater than the actual gas cost of ID calls, "15 + 3 * ceil(CALLDATASIZE / 32)". 52 | Indeed, the sufficiency is not trivial to show, but the former is simpler (thus more gas-efficient) to compute at runtime than the latter. 53 | Other calls are either private calls or calls with all available gas. 54 | */ 55 | 56 | endmodule 57 | -------------------------------------------------------------------------------- /deposit/bytecode-verification/evm.smt2: -------------------------------------------------------------------------------- 1 | ; (set-option :auto-config false) 2 | ; (set-option :smt.mbqi false) 3 | ; (set-option :smt.array.extensional false) 4 | 5 | ; int extra 6 | (define-fun int_max ((x Int) (y Int)) Int (ite (< x y) y x)) 7 | (define-fun int_min ((x Int) (y Int)) Int (ite (< x y) x y)) 8 | (define-fun int_abs ((x Int)) Int (ite (< x 0) (- 0 x) x)) 9 | 10 | ; bool to int 11 | (define-fun smt_bool2int ((b Bool)) Int (ite b 1 0)) 12 | 13 | ; IMap 14 | (define-sort IMap () (Array Int Int)) 15 | (define-fun emptyIMap () IMap ((as const IMap) 0)) 16 | 17 | ; ceil32 18 | (define-fun ceil32 ((x Int)) Int ( * ( div ( + x 31 ) 32 ) 32 ) ) 19 | 20 | ; 0 <=Int select(M, K) 21 | ;(assert (forall ((m Map) (k Int)) (<= 0 (selectInt m k)))) 22 | 23 | ; (declare-fun gas ((x Int)) Int) 24 | ; (assert (forall ((i Int) (j Int)) (=> (i > j) (< (gas i) (gas j))))) 25 | -------------------------------------------------------------------------------- /deposit/bytecode-verification/module-tmpl.k: -------------------------------------------------------------------------------- 1 | requires "abstract-semantics.k" 2 | requires "verification.k" 3 | 4 | module {MODULE}-SPEC 5 | 6 | imports ABSTRACT-SEMANTICS 7 | imports VERIFICATION 8 | 9 | {RULES} 10 | 11 | endmodule 12 | -------------------------------------------------------------------------------- /deposit/bytecode-verification/spec-tmpl.k: -------------------------------------------------------------------------------- 1 | // {RULENAME} {COMMENT} 2 | rule 3 | 4 | {K} 5 | NORMAL 6 | {SCHEDULE} 7 | 8 | 9 | {OUTPUT} 10 | {STATUS_CODE} 11 | _ => _ 12 | 13 | #parseByteStack({CODE}) 14 | #computeValidJumpDests(#parseByteStack({CODE})) 15 | {THIS} // this 16 | {MSG_SENDER} // msg.sender 17 | {CALL_DATA} // msg.data 18 | {CALL_VALUE} // msg.value 19 | {WORD_STACK} 20 | {LOCAL_MEM} 21 | {PC} 22 | {GAS} 23 | {MEMORY_USED} 24 | _ => _ 25 | false // NOTE: non-static call 26 | {CALL_DEPTH} 27 | 28 | 29 | {LOG} 30 | {REFUND} 31 | ... 32 | 33 | ... 34 | 35 | 36 | {ACTIVE_ACCOUNTS} SetItem({THIS}) SetItem(2) SetItem(4) _:Set 37 | 38 | 39 | {THIS} 40 | {BALANCE} 41 | #parseByteStack({CODE}) 42 | {STORAGE} 43 | {ORIG_STORAGE} 44 | {NONCE} 45 | 46 | 47 | // precompiled account for SHA256 48 | 2 49 | 0 50 | .WordStack 51 | .Map 52 | .Map 53 | 0 54 | 55 | 56 | // precompiled account for ID 57 | 4 58 | 0 59 | .WordStack 60 | .Map 61 | .Map 62 | 0 63 | 64 | {ACCOUNTS} 65 | ... 66 | 67 | ... 68 | 69 | 70 | ... 71 | 72 | requires true 73 | {REQUIRES} 74 | ensures true 75 | {ENSURES} 76 | {ATTRIBUTE} 77 | -------------------------------------------------------------------------------- /deposit/deposit-formal-verification.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/verified-smart-contracts/e61ef57de99d07d7182436490f152a14621c5a82/deposit/deposit-formal-verification.pdf -------------------------------------------------------------------------------- /deposit/formal-incremental-merkle-tree-algorithm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/verified-smart-contracts/e61ef57de99d07d7182436490f152a14621c5a82/deposit/formal-incremental-merkle-tree-algorithm.pdf -------------------------------------------------------------------------------- /erc20/.build/.kevm.rev: -------------------------------------------------------------------------------- 1 | 06f1d2f88c6c2769ef9ac86e26477c718c29e14c 2 | -------------------------------------------------------------------------------- /erc20/.build/concrete-rules.txt: -------------------------------------------------------------------------------- 1 | EDSL.#ceil32 2 | EDSL.keccakIntList 3 | EVM-TYPES.#signed.positive 4 | EVM-TYPES.#signed.negative 5 | EVM-TYPES.#unsigned.positive 6 | EVM-TYPES.#unsigned.negative 7 | EVM-TYPES.powmod.nonzero 8 | EVM-TYPES.powmod.zero 9 | EVM-TYPES.signextend.invalid 10 | EVM-TYPES.signextend.negative 11 | EVM-TYPES.signextend.positive 12 | SERIALIZATION.keccak 13 | EVM-TYPES.#take.zero-pad 14 | EVM-TYPES.#asWord.recursive 15 | EVM-TYPES.#asByteStack 16 | EVM-TYPES.#asByteStackAux.recursive 17 | EVM-TYPES.#padToWidth 18 | EVM-TYPES.#padRightToWidth 19 | SERIALIZATION.#newAddr 20 | SERIALIZATION.#newAddrCreate2 21 | EVM-TYPES.mapWriteBytes.recursive 22 | EVM-TYPES.#range 23 | EVM-TYPES.#lookup.some 24 | EVM-TYPES.#lookup.none 25 | EVM.#memoryUsageUpdate.some 26 | EVM.Cgascap 27 | EVM.Csstore.new 28 | EVM.Csstore.old 29 | EVM.Rsstore.new 30 | EVM.Rsstore.old 31 | EVM.Cextra 32 | EVM.Cmem 33 | -------------------------------------------------------------------------------- /erc20/README.md: -------------------------------------------------------------------------------- 1 | # Formally Verified ERC20 Token Contracts 2 | 3 | This directory contains ERC20 token contracts that have been formally verified by [Runtime Verification] and/or collaborators. 4 | 5 | Refer to the main [README] file for more details and the complete list of formally verified smart contracts. 6 | 7 | ## List of Verified ERC20 Token Contracts 8 | 9 | * **2018-03-12** [DappSys DSToken ERC20 token contract](/erc20/ds-token/README.md) 10 | * **2018-01-30** [MyKidsEducationToken ERC20 token contract](/erc20/hobby/README.md) 11 | * **2018-01-26** [OpenZeppelin ERC20 token contract](/erc20/zeppelin/README.md) 12 | * **2018-01-16** [HackerGold (HKG) ERC20 token contract](/erc20/hkg/README.md) 13 | * **2017-12-23** [Philip Daian's Vyper ERC20 token contract](/erc20/vyper/README.md) 14 | 15 | ## [Resources](/README.md#resources) 16 | 17 | ## [Disclaimer](/README.md#disclaimer) 18 | 19 | 20 | [Runtime Verification]: 21 | [README]: 22 | -------------------------------------------------------------------------------- /erc20/all/contracts/22_kucoin.sol: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at Etherscan.io on 2019-04-02 3 | */ 4 | 5 | pragma solidity ^0.4.13; 6 | 7 | 8 | 9 | contract MyToken { 10 | /* Public variables of the token */ 11 | string public name; 12 | string public symbol; 13 | uint8 public decimals; 14 | uint256 public totalSupply; 15 | 16 | /* This creates an array with all balances */ 17 | mapping (address => uint256) public balanceOf; 18 | mapping (address => mapping (address => uint256)) public allowance; 19 | 20 | /* This generates a public event on the blockchain that will notify clients */ 21 | event Transfer(address indexed from, address indexed to, uint256 value); 22 | 23 | /* This notifies clients about the amount burnt */ 24 | event Burn(address indexed from, uint256 value); 25 | 26 | /* Initializes contract with initial supply tokens to the creator of the contract */ 27 | function MyToken( 28 | uint256 initialSupply, 29 | string tokenName, 30 | uint8 decimalUnits, 31 | string tokenSymbol 32 | ) { 33 | balanceOf[msg.sender] = initialSupply; // Give the creator all initial tokens 34 | totalSupply = initialSupply; // Update total supply 35 | name = tokenName; // Set the name for display purposes 36 | symbol = tokenSymbol; // Set the symbol for display purposes 37 | decimals = decimalUnits; // Amount of decimals for display purposes 38 | } 39 | 40 | /* Internal transfer, only can be called by this contract */ 41 | function _transfer(address _from, address _to, uint _value) internal { 42 | require (_to != 0x0); // Prevent transfer to 0x0 address. Use burn() instead 43 | require (balanceOf[_from] > _value); // Check if the sender has enough 44 | require (balanceOf[_to] + _value > balanceOf[_to]); // Check for overflows 45 | balanceOf[_from] -= _value; // Subtract from the sender 46 | balanceOf[_to] += _value; // Add the same to the recipient 47 | Transfer(_from, _to, _value); 48 | } 49 | 50 | /// @notice Send `_value` tokens to `_to` from your account 51 | /// @param _to The address of the recipient 52 | /// @param _value the amount to send 53 | function transfer(address _to, uint256 _value) { 54 | _transfer(msg.sender, _to, _value); 55 | } 56 | 57 | 58 | /// @notice Remove `_value` tokens from the system irreversibly 59 | /// @param _value the amount of money to burn 60 | function burn(uint256 _value) returns (bool success) { 61 | require (balanceOf[msg.sender] > _value); // Check if the sender has enough 62 | balanceOf[msg.sender] -= _value; // Subtract from the sender 63 | totalSupply -= _value; // Updates totalSupply 64 | Burn(msg.sender, _value); 65 | return true; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /erc20/all/contracts/23_ekt.sol: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at Etherscan.io on 2019-07-12 3 | */ 4 | 5 | pragma solidity ^0.4.24; 6 | 7 | contract SafeMath { 8 | function safeMul(uint256 a, uint256 b) internal pure returns (uint256) { 9 | uint256 c = a * b; 10 | _assert(a == 0 || c / a == b); 11 | return c; 12 | } 13 | 14 | function safeDiv(uint256 a, uint256 b) internal pure returns (uint256) { 15 | _assert(b > 0); 16 | uint256 c = a / b; 17 | _assert(a == b * c + a % b); 18 | return c; 19 | } 20 | 21 | function safeSub(uint256 a, uint256 b) internal pure returns (uint256) { 22 | _assert(b <= a); 23 | return a - b; 24 | } 25 | 26 | function safeAdd(uint256 a, uint256 b) internal pure returns (uint256) { 27 | uint256 c = a + b; 28 | _assert(c >= a && c >= b); 29 | return c; 30 | } 31 | 32 | function _assert(bool assertion) internal pure { 33 | if (!assertion) { 34 | revert(); 35 | } 36 | } 37 | } 38 | 39 | contract EKT is SafeMath { 40 | string public name = "EKT"; 41 | string public symbol = "EKT"; 42 | uint8 constant public decimals = 8; 43 | mapping(address => uint256) _balances; 44 | mapping(address => mapping(address => uint256)) public _allowed; 45 | 46 | uint256 public totalSupply = 10 * 100000000 * 100000000; 47 | 48 | 49 | constructor () public{ 50 | _balances[msg.sender] = totalSupply; 51 | emit Transfer(0x0, msg.sender, totalSupply); 52 | } 53 | 54 | function balanceOf(address addr) public view returns (uint256) { 55 | return _balances[addr]; 56 | } 57 | 58 | 59 | function transfer(address _to, uint256 _value) public returns (bool) { 60 | // require(_to != address(0)); 61 | if (_to == address(0)) { 62 | return burn(_value); 63 | } else { 64 | require(_balances[msg.sender] >= _value && _value > 0); 65 | require(_balances[_to] + _value >= _balances[_to]); 66 | 67 | _balances[msg.sender] = safeSub(_balances[msg.sender], _value); 68 | _balances[_to] = safeAdd(_balances[_to], _value); 69 | emit Transfer(msg.sender, _to, _value); 70 | return true; 71 | } 72 | } 73 | 74 | function burn(uint256 _value) public returns (bool) { 75 | require(_balances[msg.sender] >= _value && _value > 0); 76 | require(totalSupply >= _value); 77 | _balances[msg.sender] = safeSub(_balances[msg.sender], _value); 78 | totalSupply = safeSub(totalSupply, _value); 79 | emit Burn(msg.sender, _value); 80 | return true; 81 | } 82 | 83 | function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { 84 | require(_to != address(0)); 85 | require(_balances[_from] >= _value && _value > 0); 86 | require(_balances[_to] + _value >= _balances[_to]); 87 | 88 | require(_allowed[_from][msg.sender] >= _value); 89 | 90 | _balances[_to] = safeAdd(_balances[_to], _value); 91 | _balances[_from] = safeSub(_balances[_from], _value); 92 | _allowed[_from][msg.sender] = safeSub(_allowed[_from][msg.sender], _value); 93 | emit Transfer(_from, _to, _value); 94 | return true; 95 | } 96 | 97 | function approve(address spender, uint256 value) public returns (bool) { 98 | require(spender != address(0)); 99 | _allowed[msg.sender][spender] = value; 100 | emit Approval(msg.sender, spender, value); 101 | return true; 102 | } 103 | 104 | function allowance(address _master, address _spender) public view returns (uint256) { 105 | return _allowed[_master][_spender]; 106 | } 107 | 108 | event Approval(address indexed _owner, address indexed _spender, uint256 _value); 109 | event Transfer(address indexed _from, address indexed _to, uint256 value); 110 | event Burn(address indexed _from, uint256 value); 111 | } 112 | -------------------------------------------------------------------------------- /erc20/all/demo-specs/Makefile: -------------------------------------------------------------------------------- 1 | include ../resources/kprove-erc20-group.mak 2 | -------------------------------------------------------------------------------- /erc20/all/demo-specs/certora-buggy.ini: -------------------------------------------------------------------------------- 1 | [pgm] 2 | compiler: "Solidity" 3 | _balances: 0 4 | _totalSupply: 1 5 | _allowances: 2 6 | code: "0x606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a9059cbb14610046575b600080fd5b341561005157600080fd5b610086600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506100a0565b604051808215151515815260200191505060405180910390f35b600080600080339250846000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151561017b57846000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054039150846000808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054019050610180565b600080fd5b816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550806000808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508573ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef876040518082815260200191505060405180910390a360019350505050929150505600a165627a7a723058200aac233736bb57132e4693d151f7765295b29ae9aa3212f10a706abdd994efed0029" 7 | -------------------------------------------------------------------------------- /erc20/all/demo-specs/certora-fixed.ini: -------------------------------------------------------------------------------- 1 | [pgm] 2 | compiler: "Solidity" 3 | _balances: 0 4 | _totalSupply: 1 5 | _allowances: 2 6 | code: "0x606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a9059cbb14610046575b600080fd5b341561005157600080fd5b610086600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506100a0565b604051808215151515815260200191505060405180910390f35b6000806000803392506000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205491506000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050846000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515610233578573ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614151561022e57846000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054039150846000808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540190505b610238565b600080fd5b816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550806000808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508573ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef876040518082815260200191505060405180910390a360019350505050929150505600a165627a7a723058207d1f2e94dd2380aa2394b4643f49b8b0c6898ace7be8838ea219638d91f89d0a0029" 7 | -------------------------------------------------------------------------------- /erc20/all/demo-specs/hkg.ini: -------------------------------------------------------------------------------- 1 | [pgm] 2 | compiler: "Solidity" 3 | _totalSupply: 0 4 | _balances: 1 5 | _allowances: 2 6 | code: "0x60606040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063095ea7b31461007257806323b872dd146100cc57806370a0823114610145578063a9059cbb14610192578063dd62ed3e146101ec575b600080fd5b341561007d57600080fd5b6100b2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610258565b604051808215151515815260200191505060405180910390f35b34156100d757600080fd5b61012b600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061034a565b604051808215151515815260200191505060405180910390f35b341561015057600080fd5b61017c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506105c6565b6040518082815260200191505060405180910390f35b341561019d57600080fd5b6101d2600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061060f565b604051808215151515815260200191505060405180910390f35b34156101f757600080fd5b610242600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610778565b6040518082815260200191505060405180910390f35b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b600081600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410158015610417575081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410155b80156104235750600082115b156105ba5781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190506105bf565b600090505b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101580156106605750600082115b1561076d5781600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360019050610772565b600090505b92915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a165627a7a723058206cb5284e8795f7d1c570318732bc1cb8add2222946156c0ba28c946531c4a2f50029" 7 | -------------------------------------------------------------------------------- /erc20/all/demo-specs/vyper.ini: -------------------------------------------------------------------------------- 1 | [pgm] 2 | compiler: "Vyper" 3 | _balances: 0 4 | _allowances: 1 5 | _totalSupply: 2 6 | code: "0x600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a05263d0e30db06000511415610168573460008112585761014052336101605261016051600060c052602060c02001546101405161016051600060c052602060c020015401116101405115176100e657600080fd5b6101405161016051600060c052602060c02001540161016051600060c052602060c020015560025461014051600254011161014051151761012657600080fd5b610140516002540160025561014051610180526101605160007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020610180a3005b632e1a7d4d6000511415610260576020600461014037341561018957600080fd5b33610160526101405161016051600060c052602060c020015410156101ad57600080fd5b6101405161016051600060c052602060c02001540361016051600060c052602060c02001556101405160025410156101e457600080fd5b61014051600254036002556000600060006000600160605161014051806040519013585780919012585702610160516000f161021f57600080fd5b61014051610180526000610160517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020610180a3600160005260206000f3005b6318160ddd600051141561028657341561027957600080fd5b60025460005260206000f3005b6370a0823160005114156102cd57602060046101403734156102a757600080fd5b60043560205181101558575061014051600060c052602060c020015460005260206000f3005b63a9059cbb60005114156103e057604060046101403734156102ee57600080fd5b60043560205181101558575033610180526101605161018051600060c052602060c0200154101561031e57600080fd5b6101605161018051600060c052602060c02001540361018051600060c052602060c020015561014051600060c052602060c02001546101605161014051600060c052602060c0200154011161016051151761037857600080fd5b6101605161014051600060c052602060c02001540161014051600060c052602060c0200155610160516101a05261014051610180517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60206101a0a3600160005260206000f3005b6323b872dd6000511415610559576060600461014037341561040157600080fd5b600435602051811015585750602435602051811015585750336101a0526101a05161014051600160c052602060c0200160c052602060c02001546101c0526101805161014051600060c052602060c0200154101561045e57600080fd5b6101805161014051600060c052602060c02001540361014051600060c052602060c020015561016051600060c052602060c02001546101805161016051600060c052602060c020015401116101805115176104b857600080fd5b6101805161016051600060c052602060c02001540161016051600060c052602060c0200155610180516101c05110156104f057600080fd5b610180516101c051036101a05161014051600160c052602060c0200160c052602060c0200155610180516101e05261016051610140517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60206101e0a3600160005260206000f3005b63095ea7b360005114156105ef576040600461014037341561057a57600080fd5b6004356020518110155857503361018052610160516101405161018051600160c052602060c0200160c052602060c0200155610160516101a05261014051610180517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560206101a0a3600160005260206000f3005b63dd62ed3e600051141561064f576040600461014037341561061057600080fd5b6004356020518110155857506024356020518110155857506101605161014051600160c052602060c0200160c052602060c020015460005260206000f3005b" 7 | -------------------------------------------------------------------------------- /erc20/all/fragments-solar/allowance.ini: -------------------------------------------------------------------------------- 1 | [allowance] 2 | +k: ~> #assume {FULL_REQUIRES} 3 | ; spec script 4 | ~> #mkCallShortcut V_CONF_BEFORE CALLER_ID ACCT_ID 5 | #abiCallData("allowance", #address(OWNER), #address(SPENDER)) V_OUT 6 | ~> #assert {FULL_ENSURES} 7 | => . 8 | FULL_REQUIRES: true 9 | andBool V_OUT ==K String2Id("V_OUT") 10 | ; types 11 | andBool #rangeAddress(OWNER) 12 | andBool #rangeAddress(SPENDER) 13 | FULL_ENSURES: true 14 | &&S (#var(V_OLD_STORAGE) ==S #getStorage(ACCT_ID)) 15 | &&S (#var(V_OLD_LOG) ==S #getLog) 16 | &&S (#var(V_OLD_REFUND) ==S #getRefund) 17 | &&S (#getStatusCode ==S EVMC_SUCCESS) 18 | &&S (#sizeByteArrayExp(#var(V_OUT)) ==S 32) 19 | -------------------------------------------------------------------------------- /erc20/all/fragments-solar/balanceOf.ini: -------------------------------------------------------------------------------- 1 | [balanceOf] 2 | +k: ~> #assume {FULL_REQUIRES} 3 | ~> #mkCallShortcut V_CONF_BEFORE CALLER_ID ACCT_ID 4 | #abiCallData("balanceOf", #address(OWNER)) V_OUT 5 | ~> #assert {FULL_ENSURES} 6 | => . 7 | FULL_REQUIRES: true 8 | andBool V_OUT ==K String2Id("V_OUT") 9 | ; types 10 | andBool #rangeAddress(OWNER) 11 | FULL_ENSURES: true 12 | &&S (#var(V_OLD_STORAGE) ==S #getStorage(ACCT_ID)) 13 | &&S (#var(V_OLD_LOG) ==S #getLog) 14 | &&S (#var(V_OLD_REFUND) ==S #getRefund) 15 | &&S (#getStatusCode ==S EVMC_SUCCESS) 16 | &&S (#sizeByteArrayExp(#var(V_OUT)) ==S 32) 17 | -------------------------------------------------------------------------------- /erc20/all/fragments-solar/root.ini: -------------------------------------------------------------------------------- 1 | [root] 2 | k: #dummy 3 | ~> #assume V_CONF_BEFORE ==K String2Id("V_CONF_BEFORE") 4 | ~> #assume V_OLD_STORAGE ==K String2Id("V_OLD_STORAGE") 5 | ~> #assume V_OLD_LOG ==K String2Id("V_OLD_LOG") 6 | ~> #assume V_OLD_REFUND ==K String2Id("V_OLD_REFUND") 7 | ~> #saveEthereum V_CONF_BEFORE 8 | ~> #saveStorage ACCT_ID V_OLD_STORAGE 9 | ~> #saveLog V_OLD_LOG 10 | ~> #saveRefund V_OLD_REFUND 11 | schedule: PETERSBURG 12 | output: _ => _ 13 | statusCode: _ => _ 14 | gas: #gas(INITGAS, 0, 0) => _ 15 | callData: _ => _ 16 | ; for view functions tested that is unchanged 17 | storage: S => _ 18 | origStorage: S 19 | ; for view functions tested that is unchanged 20 | log: _ => _ 21 | refund: _ => _ 22 | commandVars: .Map => _ 23 | requires: 24 | ensures: 25 | comment: 26 | attribute: 27 | -------------------------------------------------------------------------------- /erc20/all/fragments-solar/totalSupply.ini: -------------------------------------------------------------------------------- 1 | [totalSupply] 2 | +k: ~> #assume V_OUT ==K String2Id("V_OUT") 3 | ~> #mkCallShortcut V_CONF_BEFORE CALLER_ID ACCT_ID 4 | #abiCallData("totalSupply", .TypedArgs) V_OUT 5 | ~> #assert {FULL_ENSURES} 6 | => . 7 | FULL_ENSURES: true 8 | &&S (#var(V_OLD_STORAGE) ==S #getStorage(ACCT_ID)) 9 | &&S (#var(V_OLD_LOG) ==S #getLog) 10 | &&S (#var(V_OLD_REFUND) ==S #getRefund) 11 | &&S (#getStatusCode ==S EVMC_SUCCESS) 12 | &&S (#sizeByteArrayExp(#var(V_OUT)) ==S 32) 13 | -------------------------------------------------------------------------------- /erc20/all/fragments/allowance.ini: -------------------------------------------------------------------------------- 1 | [allowance] 2 | statusCode: _ => EVMC_SUCCESS 3 | output: _ => #buf(32, ALLOWANCE) 4 | callData: #abiCallData("allowance", #address(OWNER), #address(SPENDER)) 5 | log: _ 6 | refund: _ 7 | storage: M 8 | origStorage: _ 9 | requires: 10 | // types 11 | andBool #rangeAddress(OWNER) 12 | andBool #rangeAddress(SPENDER) 13 | andBool #rangeUInt(256, ALLOWANCE) 14 | // let-bindings 15 | andBool ALLOWANCE ==Int select(M, #hashedLocation({COMPILER}, {_ALLOWANCES}, OWNER SPENDER)) 16 | -------------------------------------------------------------------------------- /erc20/all/fragments/approve.ini: -------------------------------------------------------------------------------- 1 | [approve] 2 | statusCode: _ => SC 3 | output: _ => NEW_OUTPUT 4 | callData: #abiCallData("approve", #address(SPENDER), #uint256(VALUE)) 5 | log: OLD_LOG => NEW_LOG 6 | refund: _ => _ 7 | storage: M1 => M2 8 | origStorage: M1 9 | requires: 10 | // types 11 | andBool #rangeAddress(SPENDER) 12 | andBool #rangeUInt(256, VALUE) 13 | // let-bindings 14 | andBool OLD_ALLOWANCE ==Int select(M1, #hashedLocation({COMPILER}, {_ALLOWANCES}, CALLER_ID SPENDER)) 15 | ensures: 16 | andBool ( 17 | ( 18 | // return true 19 | SC ==K EVMC_SUCCESS 20 | andBool NEW_OUTPUT ==K #buf(32, 1) 21 | andBool NEW_LOG ==K OLD_LOG ListItem(#abiEventLog(ACCT_ID, "Approval", #indexed(#address(CALLER_ID)), #indexed(#address(SPENDER)), #uint256(VALUE))) 22 | andBool M2 ==IMap M1 [ #hashedLocation({COMPILER}, {_ALLOWANCES}, CALLER_ID SPENDER) <- VALUE ] 23 | ) orBool ( 24 | // revert 25 | SC =/=K EVMC_SUCCESS 26 | // pre-conditions 27 | {EXTRA_PRE_CONDITIONS} 28 | ) orBool ( 29 | // return false 30 | SC ==K EVMC_SUCCESS andBool NEW_OUTPUT ==K #buf(32, 0) 31 | andBool OLD_LOG ==K NEW_LOG 32 | andBool M1 ==IMap M2 33 | // pre-conditions 34 | {EXTRA_PRE_CONDITIONS} 35 | ) 36 | ) 37 | EXTRA_PRE_CONDITIONS: 38 | andBool ( 39 | ( 40 | CALLER_ID ==Int 0 41 | ) orBool ( 42 | SPENDER ==Int 0 43 | ) orBool ( 44 | VALUE ==Int 0 45 | ) orBool ( 46 | VALUE =/=Int 0 andBool OLD_ALLOWANCE =/=Int 0 /* mitigates the ERC20 spend/approval race condition */ 47 | ) orBool ( 48 | ACCT_ID ==Int SPENDER /* 04_chainlink, non-ERC20-compliant */ 49 | ) 50 | ) 51 | -------------------------------------------------------------------------------- /erc20/all/fragments/balanceOf.ini: -------------------------------------------------------------------------------- 1 | [balanceOf] 2 | statusCode: _ => EVMC_SUCCESS 3 | output: _ => #buf(32, BAL) 4 | callData: #abiCallData("balanceOf", #address(OWNER)) 5 | log: _ 6 | refund: _ 7 | storage: M 8 | origStorage: _ 9 | requires: 10 | // types 11 | andBool #rangeAddress(OWNER) 12 | andBool #rangeUInt(256, BAL) 13 | // let-bindings 14 | andBool BAL ==Int select(M, #hashedLocation({COMPILER}, {_BALANCES}, OWNER)) 15 | -------------------------------------------------------------------------------- /erc20/all/fragments/root.ini: -------------------------------------------------------------------------------- 1 | [root] 2 | k: #execute => #halt 3 | schedule: PETERSBURG 4 | gas: #gas(INITGAS, 0, 0) => _ 5 | ensures: 6 | comment: 7 | attribute: 8 | -------------------------------------------------------------------------------- /erc20/all/fragments/totalSupply.ini: -------------------------------------------------------------------------------- 1 | [totalSupply] 2 | statusCode: _ => EVMC_SUCCESS 3 | output: _ => #buf(32, TOTAL) 4 | callData: #abiCallData("totalSupply", .TypedArgs) 5 | log: _ 6 | refund: _ 7 | storage: M 8 | origStorage: _ 9 | requires: 10 | // types 11 | andBool #rangeUInt(256, TOTAL) 12 | // let-bindings 13 | andBool TOTAL ==Int select(M, #hashedLocation({COMPILER}, {_TOTALSUPPLY}, .IntList)) 14 | -------------------------------------------------------------------------------- /erc20/all/fragments/transfer.ini: -------------------------------------------------------------------------------- 1 | [transfer] 2 | callData: #abiCallData("transfer", #address(TO_ID), #uint256(VALUE)) 3 | refund: _ => _ 4 | requires: 5 | // types 6 | andBool #rangeAddress(TO_ID) 7 | andBool #rangeUInt(256, VALUE) 8 | andBool #rangeUInt(256, BAL_FROM) 9 | andBool #rangeUInt(256, BAL_TO) 10 | // let-bindings 11 | andBool BAL_FROM ==Int select(M1, #hashedLocation({COMPILER}, {_BALANCES}, CALLER_ID)) 12 | andBool BAL_TO ==Int select(M1, #hashedLocation({COMPILER}, {_BALANCES}, TO_ID)) 13 | 14 | [transfer-success] 15 | statusCode: _ => SC 16 | output: _ => NEW_OUTPUT 17 | log: OLD_LOG => NEW_LOG 18 | storage: M1 => M2 19 | origStorage: M1 20 | +requires: 21 | andBool VALUE <=Int BAL_FROM 22 | ensures: 23 | andBool ( 24 | ( 25 | // return true 26 | SC ==K EVMC_SUCCESS 27 | andBool NEW_OUTPUT ==K #buf(32, 1) 28 | andBool NEW_LOG ==K OLD_LOG ListItem(#abiEventLog(ACCT_ID, "Transfer", #indexed(#address(CALLER_ID)), #indexed(#address(TO_ID)), #uint256(VALUE))) 29 | {STORAGE_UPDATE} 30 | ) orBool ( 31 | // revert 32 | SC =/=K EVMC_SUCCESS 33 | // pre-conditions 34 | {EXTRA_PRE_CONDITIONS} 35 | ) orBool ( 36 | // return false 37 | SC ==K EVMC_SUCCESS andBool NEW_OUTPUT ==K #buf(32, 0) 38 | andBool OLD_LOG ==K NEW_LOG 39 | andBool M1 ==IMap M2 40 | // pre-conditions 41 | {EXTRA_PRE_CONDITIONS} 42 | ) 43 | ) 44 | EXTRA_PRE_CONDITIONS: 45 | andBool ( 46 | ( 47 | CALLER_ID ==Int 0 48 | ) orBool ( 49 | TO_ID ==Int 0 50 | ) orBool ( 51 | VALUE ==Int 0 /* hkg, non-ERC20-compliant */ 52 | ) orBool ( 53 | BAL_TO +Int VALUE >=Int (2 ^Int 256) 54 | ) orBool ( 55 | ACCT_ID ==Int TO_ID /* 04_chainlink, non-ERC20-compliant */ 56 | ) 57 | ) 58 | 59 | [transfer-success-regular] 60 | +requires: 61 | // conditions 62 | andBool CALLER_ID =/=Int TO_ID 63 | STORAGE_UPDATE: 64 | andBool select(M2, #hashedLocation({COMPILER}, {_BALANCES}, CALLER_ID)) ==Int BAL_FROM -Int VALUE 65 | andBool select(M2, #hashedLocation({COMPILER}, {_BALANCES}, TO_ID)) ==Int BAL_TO +Int VALUE 66 | andBool M1 ==IMap M2 except 67 | (SetItem(#hashedLocation({COMPILER}, {_BALANCES}, CALLER_ID)) 68 | SetItem(#hashedLocation({COMPILER}, {_BALANCES}, TO_ID)) .Set) 69 | 70 | [transfer-success-regular-overflow] 71 | +requires: 72 | // conditions 73 | andBool BAL_TO +Int VALUE SC 84 | output: _ => NEW_OUTPUT 85 | log: OLD_LOG => NEW_LOG 86 | storage: M1 => M2 87 | origStorage: M1 88 | +requires: 89 | andBool VALUE >Int BAL_FROM 90 | ensures: 91 | andBool ( 92 | ( 93 | // revert 94 | SC =/=K EVMC_SUCCESS 95 | ) orBool ( 96 | // return false 97 | SC ==K EVMC_SUCCESS andBool NEW_OUTPUT ==K #buf(32, 0) 98 | andBool OLD_LOG ==K NEW_LOG 99 | andBool M1 ==IMap M2 100 | ) 101 | ) 102 | -------------------------------------------------------------------------------- /erc20/all/mainnet-solar-specs/05_huobi.ini: -------------------------------------------------------------------------------- 1 | [pgm] 2 | code: "0x6060604052600436106100985763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde03811461009d578063095ea7b31461012757806318160ddd1461015d57806323b872dd14610182578063313ce567146101aa57806370a08231146101d357806395d89b41146101f2578063a9059cbb14610205578063dd62ed3e14610227575b600080fd5b34156100a857600080fd5b6100b061024c565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156100ec5780820151838201526020016100d4565b50505050905090810190601f1680156101195780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561013257600080fd5b610149600160a060020a0360043516602435610283565b604051901515815260200160405180910390f35b341561016857600080fd5b6101706102f0565b60405190815260200160405180910390f35b341561018d57600080fd5b610149600160a060020a03600435811690602435166044356102f6565b34156101b557600080fd5b6101bd610426565b60405160ff909116815260200160405180910390f35b34156101de57600080fd5b610170600160a060020a036004351661042b565b34156101fd57600080fd5b6100b0610446565b341561021057600080fd5b610149600160a060020a036004351660243561047d565b341561023257600080fd5b610170600160a060020a036004358116906024351661053a565b60408051908101604052600a81527f48756f6269546f6b656e00000000000000000000000000000000000000000000602082015281565b600160a060020a03338116600081815260016020908152604080832094871680845294909152808220859055909291907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259085905190815260200160405180910390a35060015b92915050565b60035481565b600160a060020a03808416600081815260016020908152604080832033909516835293815283822054928252819052918220548390108015906103395750828110155b801561035f5750600160a060020a03841660009081526020819052604090205483810110155b1561041957600160a060020a03808516600090815260208190526040808220805487019055918716815220805484900390556000198110156103c957600160a060020a03808616600090815260016020908152604080832033909416835292905220805484900390555b83600160a060020a031685600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8560405190815260200160405180910390a36001915061041e565b600091505b509392505050565b601281565b600160a060020a031660009081526020819052604090205490565b60408051908101604052600281527f4854000000000000000000000000000000000000000000000000000000000000602082015281565b600160a060020a0333166000908152602081905260408120548290108015906104c05750600160a060020a03831660009081526020819052604090205482810110155b1561053257600160a060020a033381166000818152602081905260408082208054879003905592861680825290839020805486019055917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a35060016102ea565b5060006102ea565b600160a060020a039182166000908152600160209081526040808320939094168252919091522054905600a165627a7a72305820c129bd269d0adfb45f74a1d569e7170c49140570d880849318201de68509f99d0029" 3 | -------------------------------------------------------------------------------- /erc20/all/mainnet-solar-specs/09_ino.ini: -------------------------------------------------------------------------------- 1 | [pgm] 2 | code: "0x6060604052600436106100b95763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100be578063095ea7b31461014857806318160ddd1461017e57806323b872dd146101a3578063313ce567146101cb57806342966c68146101f457806370a082311461020a57806379cc67901461022957806395d89b411461024b578063a9059cbb1461025e578063cae9ca5114610282578063dd62ed3e146102e7575b600080fd5b34156100c957600080fd5b6100d161030c565b60405160208082528190810183818151815260200191508051906020019080838360005b8381101561010d5780820151838201526020016100f5565b50505050905090810190601f16801561013a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015357600080fd5b61016a600160a060020a03600435166024356103aa565b604051901515815260200160405180910390f35b341561018957600080fd5b6101916103da565b60405190815260200160405180910390f35b34156101ae57600080fd5b61016a600160a060020a03600435811690602435166044356103e0565b34156101d657600080fd5b6101de610457565b60405160ff909116815260200160405180910390f35b34156101ff57600080fd5b61016a600435610460565b341561021557600080fd5b610191600160a060020a03600435166104eb565b341561023457600080fd5b61016a600160a060020a03600435166024356104fd565b341561025657600080fd5b6100d16105d9565b341561026957600080fd5b610280600160a060020a0360043516602435610644565b005b341561028d57600080fd5b61016a60048035600160a060020a03169060248035919060649060443590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061065395505050505050565b34156102f257600080fd5b610191600160a060020a0360043581169060243516610785565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103a25780601f10610377576101008083540402835291602001916103a2565b820191906000526020600020905b81548152906001019060200180831161038557829003601f168201915b505050505081565b600160a060020a033381166000908152600560209081526040808320938616835292905220819055600192915050565b60035481565b600160a060020a0380841660009081526005602090815260408083203390941683529290529081205482111561041557600080fd5b600160a060020a038085166000908152600560209081526040808320339094168352929052208054839003905561044d8484846107a2565b5060019392505050565b60025460ff1681565b600160a060020a0333166000908152600460205260408120548290101561048657600080fd5b600160a060020a03331660008181526004602052604090819020805485900390556003805485900390557fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca59084905190815260200160405180910390a2506001919050565b60046020526000908152604090205481565b600160a060020a0382166000908152600460205260408120548290101561052357600080fd5b600160a060020a038084166000908152600560209081526040808320339094168352929052205482111561055657600080fd5b600160a060020a038084166000818152600460209081526040808320805488900390556005825280832033909516835293905282902080548590039055600380548590039055907fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca59084905190815260200160405180910390a250600192915050565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103a25780601f10610377576101008083540402835291602001916103a2565b61064f3383836107a2565b5050565b60008361066081856103aa565b1561077d5780600160a060020a0316638f4ffcb1338630876040518563ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018085600160a060020a0316600160a060020a0316815260200184815260200183600160a060020a0316600160a060020a0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107165780820151838201526020016106fe565b50505050905090810190601f1680156107435780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b151561076457600080fd5b6102c65a03f1151561077557600080fd5b505050600191505b509392505050565b600560209081526000928352604080842090915290825290205481565b6000600160a060020a03831615156107b957600080fd5b600160a060020a038416600090815260046020526040902054829010156107df57600080fd5b600160a060020a0383166000908152600460205260409020548281011161080557600080fd5b50600160a060020a0380831660008181526004602052604080822080549488168084528284208054888103909155938590528154870190915591909301927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a3600160a060020a038084166000908152600460205260408082205492871682529020540181146108a257fe5b505050505600a165627a7a72305820481e18755cb30fe23e13dc47857a7a81f01d1cceeccdb4e3c669a72b7b4633310029" 3 | -------------------------------------------------------------------------------- /erc20/all/mainnet-solar-specs/Makefile: -------------------------------------------------------------------------------- 1 | FRAGMENT_INI_DIR=$(abspath $(THIS_FILE_DIR)/../fragments-solar) 2 | KPROVE_MAK_FILE=$(LOCAL_RESOURCES_DIR)/kprove-erc20-solar.mak 3 | 4 | include ../resources/kprove-erc20-group.mak 5 | -------------------------------------------------------------------------------- /erc20/all/mainnet-solar-test/Makefile: -------------------------------------------------------------------------------- 1 | override IGNORE_ERRORS_OPT:= 2 | FRAGMENT_INI_DIR=$(abspath $(THIS_FILE_DIR)/../fragments-solar) 3 | KPROVE_MAK_FILE=$(LOCAL_RESOURCES_DIR)/kprove-erc20-solar.mak 4 | 5 | include ../resources/kprove-erc20-group.mak 6 | -------------------------------------------------------------------------------- /erc20/all/mainnet-specs/05_huobi.ini: -------------------------------------------------------------------------------- 1 | [pgm] 2 | compiler: "Solidity" 3 | _totalSupply: 2 4 | _balances: 0 5 | _allowances: 1 6 | code: "0x6060604052600436106100985763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde03811461009d578063095ea7b31461012757806318160ddd1461015d57806323b872dd14610182578063313ce567146101aa57806370a08231146101d357806395d89b41146101f2578063a9059cbb14610205578063dd62ed3e14610227575b600080fd5b34156100a857600080fd5b6100b061024c565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156100ec5780820151838201526020016100d4565b50505050905090810190601f1680156101195780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561013257600080fd5b610149600160a060020a0360043516602435610283565b604051901515815260200160405180910390f35b341561016857600080fd5b6101706102f0565b60405190815260200160405180910390f35b341561018d57600080fd5b610149600160a060020a03600435811690602435166044356102f6565b34156101b557600080fd5b6101bd610426565b60405160ff909116815260200160405180910390f35b34156101de57600080fd5b610170600160a060020a036004351661042b565b34156101fd57600080fd5b6100b0610446565b341561021057600080fd5b610149600160a060020a036004351660243561047d565b341561023257600080fd5b610170600160a060020a036004358116906024351661053a565b60408051908101604052600a81527f48756f6269546f6b656e00000000000000000000000000000000000000000000602082015281565b600160a060020a03338116600081815260016020908152604080832094871680845294909152808220859055909291907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259085905190815260200160405180910390a35060015b92915050565b60035481565b600160a060020a03808416600081815260016020908152604080832033909516835293815283822054928252819052918220548390108015906103395750828110155b801561035f5750600160a060020a03841660009081526020819052604090205483810110155b1561041957600160a060020a03808516600090815260208190526040808220805487019055918716815220805484900390556000198110156103c957600160a060020a03808616600090815260016020908152604080832033909416835292905220805484900390555b83600160a060020a031685600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8560405190815260200160405180910390a36001915061041e565b600091505b509392505050565b601281565b600160a060020a031660009081526020819052604090205490565b60408051908101604052600281527f4854000000000000000000000000000000000000000000000000000000000000602082015281565b600160a060020a0333166000908152602081905260408120548290108015906104c05750600160a060020a03831660009081526020819052604090205482810110155b1561053257600160a060020a033381166000818152602081905260408082208054879003905592861680825290839020805486019055917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a35060016102ea565b5060006102ea565b600160a060020a039182166000908152600160209081526040808320939094168252919091522054905600a165627a7a72305820c129bd269d0adfb45f74a1d569e7170c49140570d880849318201de68509f99d0029" 7 | -------------------------------------------------------------------------------- /erc20/all/mainnet-specs/Makefile: -------------------------------------------------------------------------------- 1 | include ../resources/kprove-erc20-group.mak 2 | -------------------------------------------------------------------------------- /erc20/all/mainnet-test/Makefile: -------------------------------------------------------------------------------- 1 | override IGNORE_ERRORS_OPT:= 2 | 3 | include ../resources/kprove-erc20-group.mak 4 | -------------------------------------------------------------------------------- /erc20/all/resources/get-bytecode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Prerequisites: pip install pyetherchain 4 | # 5 | # usage: python3 get-bytecode.py
6 | 7 | import sys 8 | from pyetherchain.pyetherchain import EtherChain 9 | 10 | 11 | def main(): 12 | address = sys.argv[1] 13 | print(EtherChain().account(address).code) 14 | 15 | 16 | if __name__ == '__main__': 17 | main() 18 | -------------------------------------------------------------------------------- /erc20/all/resources/kprove-erc20-group.mak: -------------------------------------------------------------------------------- 1 | THIS_FILE_DIR:=$(dir $(realpath $(lastword $(MAKEFILE_LIST)))) 2 | 3 | # 4 | # Parameters 5 | 6 | NPROCS?=2 7 | TIMEOUT?= 8 | FRAGMENT_INI_DIR?=$(abspath $(THIS_FILE_DIR)/../fragments) 9 | KPROVE_MAK_FILE?=$(LOCAL_RESOURCES_DIR)/kprove-erc20.mak 10 | 11 | # 12 | # Settings 13 | 14 | # java or haskell 15 | K_BACKEND?=java 16 | 17 | IGNORE_ERRORS_OPT:=--ignore-errors 18 | LOCAL_RESOURCES_DIR:=$(THIS_FILE_DIR) 19 | ROOT:=$(abspath $(THIS_FILE_DIR)/../../..) 20 | RELATIVE_CURDIR:=$(strip $(patsubst $(ROOT)/%, %, $(filter $(ROOT)/%, $(CURDIR)))) 21 | SPECS_DIR:=$(ROOT)/specs/$(K_BACKEND) 22 | FRAGMENT_INI_FILES:=$(sort $(wildcard $(FRAGMENT_INI_DIR)/*.ini)) 23 | MAIN_INI_FILES:=$(sort $(wildcard *.ini)) 24 | SPEC_INI_FILES:=$(patsubst %.ini, $(SPECS_DIR)/$(RELATIVE_CURDIR)/%/erc20-spec.ini, $(MAIN_INI_FILES)) 25 | 26 | # 27 | # Tasks 28 | 29 | .PHONY: test concat split-proof-tests clean deps clean-deps 30 | 31 | test: $(SPEC_INI_FILES:=.test) 32 | 33 | # Makes $(SPEC_INI_FILES) non-intermediary 34 | concat: $(SPEC_INI_FILES) 35 | 36 | split-proof-tests: $(SPEC_INI_FILES:=.split-proof-tests) 37 | 38 | clean: 39 | rm -rf $(SPECS_DIR) 40 | 41 | deps: 42 | $(MAKE) -f $(KPROVE_MAK_FILE) deps SPEC_GROUP=resources SPEC_INI=mock.ini 43 | 44 | clean-deps: 45 | $(MAKE) -f $(KPROVE_MAK_FILE) clean-deps SPEC_GROUP=resources SPEC_INI=mock.ini 46 | 47 | .SECONDEXPANSION: 48 | $(SPECS_DIR)/%/erc20-spec.ini: $$(notdir $$*).ini $(FRAGMENT_INI_FILES) 49 | mkdir -p $(dir $@) 50 | cat $(FRAGMENT_INI_FILES) $(CURDIR)/$(notdir $*).ini > $@ 51 | 52 | # Calling "clean-kevm-cache all" here leads to very long parse times on Jenkins, 30m+ on some specs, doesn't finish in 12+ hours. 53 | $(SPECS_DIR)/%/erc20-spec.ini.split-proof-tests: $(SPECS_DIR)/%/erc20-spec.ini 54 | $(MAKE) -f $(KPROVE_MAK_FILE) all SPEC_GROUP=$* SPEC_INI=$(basename $@) 55 | 56 | $(SPECS_DIR)/%/erc20-spec.ini.test: $(SPECS_DIR)/%/erc20-spec.ini.split-proof-tests 57 | $(MAKE) -f $(KPROVE_MAK_FILE) test SPEC_GROUP=$* SPEC_INI=$(basename $@) TIMEOUT=$(TIMEOUT) $(IGNORE_ERRORS_OPT) -j$(NPROCS) 58 | 59 | # Command to run just one spec. Argument: .test 60 | # patsubst below needed because $(dir ...) leaves a trailing slash. 61 | # TODO define function mydir - same as dir but without trailing slash 62 | .SECONDEXPANSION: 63 | $(SPECS_DIR)/%-spec.k.test: $$(dir $$@)erc20-spec.ini 64 | $(MAKE) -f $(KPROVE_MAK_FILE) $@ SPEC_GROUP=$(patsubst %/,%,$(dir $*)) SPEC_INI=$(dir $@)erc20-spec.ini TIMEOUT=$(TIMEOUT) 65 | -------------------------------------------------------------------------------- /erc20/all/resources/kprove-erc20-solar.mak: -------------------------------------------------------------------------------- 1 | THIS_FILE_DIR:=$(dir $(realpath $(lastword $(MAKEFILE_LIST)))) 2 | SOLAR_DIR=$(ROOT_DIR)/erc20/solar 3 | 4 | KEVM_VERSION_FILE=$(ROOT_DIR)/erc20/.build/.kevm.rev 5 | KOMPILE_COMMAND=make build-specs K_BIN=$(K_BIN) 6 | override KEVM_BUILD_LAST_DIR=specs 7 | 8 | DEFINITION_MODULE:=VERIFICATION-SOLAR 9 | override LOCAL_LEMMAS=$(SOLAR_DIR)/verification-solar.k \ 10 | $(ROOT_DIR)/erc20/verification.k \ 11 | $(RESOURCES_DIR)/abstract-semantics-segmented-gas.k \ 12 | $(RESOURCES_DIR)/evm-symbolic.k \ 13 | $(ROOT_DIR)/erc20/evm-data-map-symbolic.k \ 14 | $(SOLAR_DIR)/solar-abstract-semantics.k 15 | override TMPLS=$(SOLAR_DIR)/module-tmpl.k $(SOLAR_DIR)/spec-tmpl.k 16 | 17 | include $(THIS_FILE_DIR)/kprove-erc20.mak 18 | -------------------------------------------------------------------------------- /erc20/all/resources/kprove-erc20.mak: -------------------------------------------------------------------------------- 1 | THIS_FILE_DIR:=$(dir $(realpath $(lastword $(MAKEFILE_LIST)))) 2 | ROOT_DIR:=$(abspath $(THIS_FILE_DIR)/../../..) 3 | RESOURCES_DIR:=$(ROOT_DIR)/resources 4 | LOCAL_RESOURCES_DIR:=$(THIS_FILE_DIR) 5 | 6 | KEVM_VERSION_FILE:=$(ROOT_DIR)/erc20/.build/.kevm.rev 7 | BASEDIR_LEMMAS=$(RESOURCES)/lemmas-buf.md 8 | LOCAL_LEMMAS:=$(ROOT_DIR)/erc20/verification.k \ 9 | $(RESOURCES_DIR)/abstract-semantics-segmented-gas.k \ 10 | $(RESOURCES_DIR)/evm-symbolic.k \ 11 | $(ROOT_DIR)/erc20/evm-data-map-symbolic.k 12 | TMPLS:=../../module-tmpl.k $(LOCAL_RESOURCES_DIR)/spec-tmpl.k 13 | 14 | SPEC_NAMES:=totalSupply \ 15 | balanceOf \ 16 | allowance \ 17 | approve \ 18 | transfer-success-regular \ 19 | transfer-success-regular-overflow \ 20 | transfer-success-self \ 21 | transfer-failure \ 22 | transferFrom-success-regular \ 23 | transferFrom-success-regular-overflow \ 24 | transferFrom-success-self \ 25 | transferFrom-failure 26 | 27 | KPROVE_OPTS:=--smt-prelude $(ROOT_DIR)/resources/evm.smt2 28 | 29 | include $(RESOURCES_DIR)/kprove.mak 30 | -------------------------------------------------------------------------------- /erc20/all/resources/spec-tmpl.k: -------------------------------------------------------------------------------- 1 | // {RULENAME} {COMMENT} 2 | rule 3 | {K} 4 | 1 5 | NORMAL 6 | {SCHEDULE} 7 | 8 | 9 | 10 | {OUTPUT} 11 | {STATUSCODE} 12 | _ 13 | _ 14 | _ => _ 15 | 16 | #parseByteStack({CODE}) 17 | #computeValidJumpDests(#parseByteStack({CODE})) 18 | ACCT_ID // this 19 | CALLER_ID // msg.sender 20 | {CALLDATA} // msg.data 21 | 0 // msg.value 22 | .WordStack => _ 23 | .Map => _ 24 | 0 => _ 25 | {GAS} 26 | 0 => _ 27 | _ => _ 28 | false // NOTE: non-static call 29 | CALL_DEPTH 30 | 31 | 32 | _ 33 | {LOG} 34 | {REFUND} 35 | 36 | _ 37 | ORIGIN_ID // tx.origin 38 | _ 39 | 40 | _ 41 | _ 42 | _ 43 | _ 44 | _ 45 | _ 46 | _ 47 | _ 48 | _ 49 | _ 50 | _ 51 | _ 52 | _ 53 | _ 54 | _ 55 | 56 | _ 57 | 58 | 59 | 60 | 0 61 | SetItem(ACCT_ID) _:Set 62 | 63 | 64 | ACCT_ID 65 | _ 66 | #parseByteStack({CODE}) 67 | {STORAGE} 68 | {ORIGSTORAGE} 69 | _ 70 | 71 | ... 72 | 73 | _ 74 | _ 75 | _ 76 | 77 | 78 | requires #rangeAddress(ACCT_ID) 79 | andBool #rangeAddress(CALLER_ID) 80 | andBool #rangeAddress(ORIGIN_ID) 81 | andBool #range(0 <= CALL_DEPTH < 1024) 82 | {REQUIRES} 83 | ensures true 84 | {ENSURES} 85 | {ATTRIBUTE} 86 | -------------------------------------------------------------------------------- /erc20/ds-token/Makefile: -------------------------------------------------------------------------------- 1 | #BUILD_DIR:=../.build 2 | 3 | LOCAL_LEMMAS:=../resources-concrete/verification.k \ 4 | ../../resources/abstract-semantics-segmented-gas.k \ 5 | ../../resources/evm-symbolic.k \ 6 | ../../resources/evm-data-map-concrete.k 7 | TMPLS:=../module-tmpl.k ../spec-tmpl.k 8 | 9 | SPEC_NAMES:=totalSupply \ 10 | balanceOf \ 11 | allowance \ 12 | approve-success \ 13 | approve-failure \ 14 | transfer-success-1 \ 15 | transfer-success-2 \ 16 | transfer-failure-1-a \ 17 | transfer-failure-1-b \ 18 | transfer-failure-1-c \ 19 | transfer-failure-2-a \ 20 | transfer-failure-2-b \ 21 | transferFrom-success-1 \ 22 | transferFrom-success-2 \ 23 | transferFrom-failure-1-a \ 24 | transferFrom-failure-1-b \ 25 | transferFrom-failure-1-c \ 26 | transferFrom-failure-1-d \ 27 | transferFrom-failure-2-a \ 28 | transferFrom-failure-2-b \ 29 | transferFrom-failure-2-c 30 | 31 | include ../../resources/kprove.mak 32 | -------------------------------------------------------------------------------- /erc20/ds-token/base.sol: -------------------------------------------------------------------------------- 1 | /// base.sol -- basic ERC20 implementation 2 | 3 | // Copyright (C) 2015, 2016, 2017 DappHub, LLC 4 | 5 | // Licensed under the Apache License, Version 2.0 (the "License"). 6 | // You may not use this file except in compliance with the License. 7 | 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND (express or implied). 11 | 12 | pragma solidity ^0.4.10; 13 | 14 | import "erc20/erc20.sol"; 15 | import "ds-math/math.sol"; 16 | 17 | contract DSTokenBase is ERC20, DSMath { 18 | uint256 _supply; 19 | mapping (address => uint256) _balances; 20 | mapping (address => mapping (address => uint256)) _approvals; 21 | 22 | function DSTokenBase(uint256 supply) { 23 | _balances[msg.sender] = supply; 24 | _supply = supply; 25 | } 26 | 27 | function totalSupply() constant returns (uint256) { 28 | return _supply; 29 | } 30 | function balanceOf(address src) constant returns (uint256) { 31 | return _balances[src]; 32 | } 33 | function allowance(address src, address guy) constant returns (uint256) { 34 | return _approvals[src][guy]; 35 | } 36 | 37 | function transfer(address dst, uint wad) returns (bool) { 38 | assert(_balances[msg.sender] >= wad); 39 | 40 | _balances[msg.sender] = sub(_balances[msg.sender], wad); 41 | _balances[dst] = add(_balances[dst], wad); 42 | 43 | Transfer(msg.sender, dst, wad); 44 | 45 | return true; 46 | } 47 | 48 | function transferFrom(address src, address dst, uint wad) returns (bool) { 49 | assert(_balances[src] >= wad); 50 | assert(_approvals[src][msg.sender] >= wad); 51 | 52 | _approvals[src][msg.sender] = sub(_approvals[src][msg.sender], wad); 53 | _balances[src] = sub(_balances[src], wad); 54 | _balances[dst] = add(_balances[dst], wad); 55 | 56 | Transfer(src, dst, wad); 57 | 58 | return true; 59 | } 60 | 61 | function approve(address guy, uint256 wad) returns (bool) { 62 | _approvals[msg.sender][guy] = wad; 63 | 64 | Approval(msg.sender, guy, wad); 65 | 66 | return true; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /erc20/ds-token/token.sol: -------------------------------------------------------------------------------- 1 | /// token.sol -- ERC20 implementation with minting and burning 2 | 3 | // Copyright (C) 2015, 2016, 2017 DappHub, LLC 4 | 5 | // Licensed under the Apache License, Version 2.0 (the "License"). 6 | // You may not use this file except in compliance with the License. 7 | 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND (express or implied). 11 | 12 | pragma solidity ^0.4.10; 13 | 14 | import "ds-stop/stop.sol"; 15 | 16 | import "./base.sol"; 17 | 18 | contract DSToken is DSTokenBase(0), DSStop { 19 | 20 | bytes32 public symbol; 21 | uint256 public decimals = 18; // standard token precision. override to customize 22 | 23 | function DSToken(bytes32 symbol_) { 24 | symbol = symbol_; 25 | } 26 | 27 | function transfer(address dst, uint wad) stoppable note returns (bool) { 28 | return super.transfer(dst, wad); 29 | } 30 | function transferFrom( 31 | address src, address dst, uint wad 32 | ) stoppable note returns (bool) { 33 | return super.transferFrom(src, dst, wad); 34 | } 35 | function approve(address guy, uint wad) stoppable note returns (bool) { 36 | return super.approve(guy, wad); 37 | } 38 | 39 | function push(address dst, uint128 wad) returns (bool) { 40 | return transfer(dst, wad); 41 | } 42 | function pull(address src, uint128 wad) returns (bool) { 43 | return transferFrom(src, msg.sender, wad); 44 | } 45 | 46 | function mint(uint128 wad) auth stoppable note { 47 | _balances[msg.sender] = add(_balances[msg.sender], wad); 48 | _supply = add(_supply, wad); 49 | } 50 | function burn(uint128 wad) auth stoppable note { 51 | _balances[msg.sender] = sub(_balances[msg.sender], wad); 52 | _supply = sub(_supply, wad); 53 | } 54 | 55 | // Optional token name 56 | 57 | bytes32 public name = ""; 58 | 59 | function setName(bytes32 name_) auth { 60 | name = name_; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /erc20/gno/Makefile: -------------------------------------------------------------------------------- 1 | #BUILD_DIR:=../.build 2 | 3 | LOCAL_LEMMAS:=../resources-concrete/verification.k \ 4 | ../../resources/abstract-semantics-segmented-gas.k \ 5 | ../../resources/evm-symbolic.k \ 6 | ../../resources/evm-data-map-concrete.k 7 | TMPLS:=../module-tmpl.k spec-tmpl.k 8 | 9 | SPEC_NAMES:=totalSupply-success \ 10 | totalSupply-failure \ 11 | balanceOf-success \ 12 | balanceOf-failure \ 13 | allowance-success \ 14 | allowance-failure \ 15 | approve-success \ 16 | approve-failure \ 17 | transfer-success-1 \ 18 | transfer-success-2 \ 19 | transfer-failure-1 \ 20 | transfer-failure-2 \ 21 | transfer-failure-3 \ 22 | transferFrom-success-1 \ 23 | transferFrom-success-2 \ 24 | transferFrom-failure-1 \ 25 | transferFrom-failure-2 \ 26 | transferFrom-failure-3 27 | 28 | include ../../resources/kprove.mak 29 | -------------------------------------------------------------------------------- /erc20/gno/README.md: -------------------------------------------------------------------------------- 1 | # Formal Verification of GNO ERC20 Token 2 | 3 | By Dominik Teiml (dominik@gnosis.pm), [Gnosis](https://www.gnosis.pm) 4 | 5 | We formally verified the GNO ERC20 token contract [runtime bytecode](./gno-erc20.bytes). 6 | 7 | We found the following deviations from [ERC20-EVM](../vyper/vyper-erc20-spec.ini): 8 | 9 | - In the [high-level Solidity code](https://etherscan.io/address/0x6810e776880c02933d47db1b9fc05908e5386b96#code), mapping of users' allowances is called `allowed`, hence we use that in our [spec template](./gno-erc20-spec.ini). 10 | - To verify full security, we have added failure cases to every function for when the `callValue` is not 0. 11 | - In `transfer-failure-1` and `transferFrom-failure-1`, `BAL_TO +Int VALUE >=Int (2 ^Int 256)` was removed from the constraint. The reason is the GNO was constructed with a fixed supply of 10 M. We present a pen & paper proof that the sum will always be 10 M below. 12 | - A new lemma was added to be added to [lemmas.md](../../resources/lemmas.md) to help K tool with the reduction of a specific term. We present the lemma as well as its soundness proof: 13 | 14 | ## Token Balances Sum Invariant 15 | 16 | Proposition: 17 | 18 | Except during a tx execution, sum of all token balances will always be 10 M. 19 | 20 | Proof: 21 | 22 | In the [spec](./gno-erc20-spec.ini), the `` term is always of the form `Location_i |-> Expr_i _:Map` for $0\leq i \leq 3$, where `Expr_i` is either a variable or a rewrite rules. 23 | 24 | Due to the way K framework works, the only storage locations that can be different after execution will be `Location_i` for $0 \leq i \leq 3$. It follows that the invariance must be checked only on the `Expr_i` terms for all function cases. We present such a proof: 25 | 26 | - totalSupply, balanceOf, allowances - do not modify storage 27 | - approve - does not modify `balances` 28 | - transfer-success-1 & transferFrom-success-1 29 | - sum of expressions before: `BAL_FROM + BAL_TO` 30 | - sum of expressions after: `(BAL_FROM - VALUE) + (BAL_TO + VALUE)` = `BAL_FROM + BAL_TO` since we are assuming neither expression overflows 31 | - transfer-success-2 & transferFrom-success-2 - do not modify storage 32 | - transfer-failure & transferFrom-failure - all 3 cases lead to either EVMC_REVERT or EVMC_INVALID_INSTRUCTION, reverting all state changes 33 | 34 | QED 35 | 36 | 37 | ## Lemma 38 | 39 | Lemma: 40 | ``` 41 | rule chop ( W0:Int +Int W1:Int ) -Word W1:Int => chop ( W0 ) 42 | ``` 43 | 44 | Proof: 45 | We start with the definition of chop: 46 | 47 | ``` 48 | rule chop ( I:Int ) => I modInt pow256 49 | ``` 50 | 51 | where modInt is java's `mod` operator on BigIntegers. 52 | 53 | Hence: 54 | 55 | chop ( X ) = chop ( Y ) iff X ≡ Y (mod 2^256), and 56 | 57 | chop ( X ) ≡ X (mod 2^256) 58 | 59 | -Word is defined: 60 | 61 | ``` 62 | rule W0 -Word W1 => chop( W0 -Int W1 ) requires W0 >=Int W1 63 | rule W0 -Word W1 => chop( (W0 +Int pow256) -Int W1 ) requires W0 = b 67 | 68 | Then LHS = chop ( chop ( a + b) - b) 69 | 70 | Now chop ( a + b ) ≡ a + b (mod 2^256), 71 | 72 | so chop ( a + b ) - b ≡ a, 73 | 74 | so chop ( chop ( a + b) - b) = chop ( a ) 75 | 76 | 77 | When chop ( a + b ) < b, we get 78 | 79 | LHS = chop ( chop ( a + b) + 2^256 - b) and the rest is analogous. 80 | 81 | QED 82 | 83 | ## Conlusion 84 | 85 | In conclusion, the contract adheres to the desired behavior & our formal specification. 86 | -------------------------------------------------------------------------------- /erc20/gno/spec-tmpl.k: -------------------------------------------------------------------------------- 1 | // {RULENAME} 2 | rule 3 | {K} 4 | 1 5 | NORMAL 6 | BYZANTIUM 7 | 8 | 9 | 10 | {OUTPUT} 11 | {STATUSCODE} 12 | _ 13 | _ 14 | _ => _ 15 | 16 | 17 | #parseByteStack({CODE}) 18 | #computeValidJumpDests(#parseByteStack({CODE})) 19 | 20 | ACCT_ID // contract owner 21 | CALLER_ID // who called this contract; in the begining, origin // msg.sender 22 | 23 | {CALLDATA} 24 | 25 | {CALLVALUE} 26 | .WordStack => _ 27 | .Map => _ 28 | 0 => _ 29 | {GAS} 30 | 0 => _ 31 | _ => _ 32 | 33 | false // NOTE: non-static call 34 | CALL_DEPTH 35 | 36 | 37 | 38 | _ 39 | {LOG} 40 | {REFUND} // TODO: more detail 41 | 42 | 43 | _ 44 | ORIGIN_ID // who fires tx 45 | _ 46 | 47 | _ 48 | _ 49 | _ 50 | _ 51 | _ 52 | _ 53 | _ 54 | _ 55 | _ 56 | _ 57 | _ 58 | _ 59 | _ 60 | _ 61 | _ 62 | 63 | _ 64 | 65 | 66 | 67 | 68 | 0 69 | SetItem(ACCT_ID) _:Set 70 | 71 | 72 | 73 | ACCT_ID 74 | _ 75 | #parseByteStack({CODE}) 76 | 77 | {STORAGE} 78 | 79 | _ 80 | _ 81 | 82 | ... 83 | 84 | 85 | _ 86 | _ 87 | _ 88 | 89 | 90 | requires 0 <=Int ACCT_ID andBool ACCT_ID (RETURN RET_ADDR:Int 32 ~> _) 6 | +k: #execute => #exception 7 | callData: #abiCallData("totalSupply", .TypedArgs) 8 | -localMem: .Map => ( .Map[ RET_ADDR := #asByteStackInWidth(TOTAL, 32) ] _:Map ) 9 | +localMem: .Map => _:Map 10 | gas: {GASCAP} => _ 11 | log: _ 12 | refund: _ 13 | -storage: 14 | - #hashedLocation({COMPILER}, {_TOTALSUPPLY}, .IntList) |-> TOTAL 15 | - _:Map 16 | +storage: _:Map 17 | requires: 18 | - andBool 0 <=Int TOTAL andBool TOTAL (RETURN RET_ADDR:Int 32 ~> _) 22 | @@ -75,12 +72,12 @@ 23 | [transfer-success-1] 24 | storage: 25 | #hashedLocation({COMPILER}, {_BALANCES}, CALLER_ID) |-> (BAL_FROM => BAL_FROM -Int VALUE) 26 | - #hashedLocation({COMPILER}, {_BALANCES}, TO_ID) |-> (BAL_TO => BAL_TO +Int VALUE) 27 | + #hashedLocation({COMPILER}, {_BALANCES}, TO_ID) |-> (BAL_TO => BAL_TO +Word VALUE) 28 | _:Map 29 | +requires: 30 | andBool CALLER_ID =/=Int TO_ID 31 | andBool VALUE <=Int BAL_FROM 32 | - andBool BAL_TO +Int VALUE Int 0 34 | 35 | [transfer-success-2] 36 | storage: 37 | @@ -89,10 +86,11 @@ 38 | +requires: 39 | andBool CALLER_ID ==Int TO_ID 40 | andBool VALUE <=Int BAL_FROM 41 | + andBool VALUE >Int 0 42 | 43 | [transfer-failure] 44 | -k: #execute => #exception 45 | -localMem: .Map => _:Map 46 | +k: #execute => (RETURN RET_ADDR:Int 32 ~> _) 47 | +localMem: .Map => ( .Map[ RET_ADDR := #asByteStackInWidth(0, 32) ] _:Map ) 48 | log: _ 49 | 50 | [transfer-failure-1] 51 | @@ -103,7 +101,7 @@ 52 | +requires: 53 | andBool CALLER_ID =/=Int TO_ID 54 | andBool ( VALUE >Int BAL_FROM 55 | - orBool BAL_TO +Int VALUE >=Int (2 ^Int 256) ) 56 | + orBool VALUE <=Int 0 ) 57 | 58 | [transfer-failure-2] 59 | storage: 60 | @@ -111,7 +109,8 @@ 61 | _:Map 62 | +requires: 63 | andBool CALLER_ID ==Int TO_ID 64 | - andBool VALUE >Int BAL_FROM 65 | + andBool ( VALUE >Int BAL_FROM 66 | + orBool VALUE <=Int 0 ) 67 | 68 | [transferFrom] 69 | callData: #abiCallData("transferFrom", #address(FROM_ID), #address(TO_ID), #uint256(VALUE)) 70 | @@ -133,14 +132,14 @@ 71 | [transferFrom-success-1] 72 | storage: 73 | #hashedLocation({COMPILER}, {_BALANCES}, FROM_ID) |-> (BAL_FROM => BAL_FROM -Int VALUE) 74 | - #hashedLocation({COMPILER}, {_BALANCES}, TO_ID) |-> (BAL_TO => BAL_TO +Int VALUE) 75 | + #hashedLocation({COMPILER}, {_BALANCES}, TO_ID) |-> (BAL_TO => BAL_TO +Word VALUE) 76 | #hashedLocation({COMPILER}, {_ALLOWANCES}, FROM_ID CALLER_ID) |-> (ALLOW => ALLOW -Int VALUE) 77 | _:Map 78 | +requires: 79 | andBool FROM_ID =/=Int TO_ID 80 | andBool VALUE <=Int BAL_FROM 81 | - andBool BAL_TO +Int VALUE Int 0 84 | 85 | [transferFrom-success-2] 86 | storage: 87 | @@ -151,10 +150,11 @@ 88 | andBool FROM_ID ==Int TO_ID 89 | andBool VALUE <=Int BAL_FROM 90 | andBool VALUE <=Int ALLOW 91 | + andBool VALUE >Int 0 92 | 93 | [transferFrom-failure] 94 | -k: #execute => #exception 95 | -localMem: .Map => _:Map 96 | +k: #execute => (RETURN RET_ADDR:Int 32 ~> _) 97 | +localMem: .Map => ( .Map[ RET_ADDR := #asByteStackInWidth(0, 32) ] _:Map ) 98 | log: _ 99 | 100 | [transferFrom-failure-1] 101 | @@ -166,8 +166,8 @@ 102 | +requires: 103 | andBool FROM_ID =/=Int TO_ID 104 | andBool ( VALUE >Int BAL_FROM 105 | - orBool BAL_TO +Int VALUE >=Int (2 ^Int 256) 106 | - orBool VALUE >Int ALLOW ) 107 | + orBool VALUE >Int ALLOW 108 | + orBool VALUE <=Int 0 ) 109 | 110 | [transferFrom-failure-2] 111 | storage: 112 | @@ -177,12 +177,14 @@ 113 | +requires: 114 | andBool FROM_ID ==Int TO_ID 115 | andBool ( VALUE >Int BAL_FROM 116 | - orBool VALUE >Int ALLOW ) 117 | + orBool VALUE >Int ALLOW 118 | + orBool VALUE <=Int 0 ) 119 | -------------------------------------------------------------------------------- /erc20/hobby/Makefile: -------------------------------------------------------------------------------- 1 | #BUILD_DIR:=../.build 2 | 3 | LOCAL_LEMMAS:=../resources-concrete/verification.k \ 4 | ../../resources/abstract-semantics-segmented-gas.k \ 5 | ../../resources/evm-symbolic.k \ 6 | ../../resources/evm-data-map-concrete.k 7 | TMPLS:=../module-tmpl.k ../spec-tmpl.k 8 | 9 | SPEC_NAMES:=totalSupply \ 10 | balanceOf \ 11 | allowance \ 12 | approve-success \ 13 | approve-failure \ 14 | transfer-success-1 \ 15 | transfer-success-2 \ 16 | transfer-failure-1 \ 17 | transfer-failure-2 \ 18 | transferFrom-success-1 \ 19 | transferFrom-success-2 \ 20 | transferFrom-failure-1 \ 21 | transferFrom-failure-2 22 | 23 | include ../../resources/kprove.mak 24 | -------------------------------------------------------------------------------- /erc20/hobby/MyKidsEducationToken.fixed.gist: -------------------------------------------------------------------------------- 1 | https://gist.github.com/anonymous/06f04e32f80583b4db3dffb9cb341830 2 | -------------------------------------------------------------------------------- /erc20/module-tmpl.k: -------------------------------------------------------------------------------- 1 | requires "abstract-semantics-segmented-gas.k" 2 | requires "verification.k" 3 | 4 | module {MODULE}-SPEC 5 | imports ABSTRACT-SEMANTICS-SEGMENTED-GAS 6 | imports VERIFICATION 7 | 8 | {RULES} 9 | 10 | endmodule 11 | -------------------------------------------------------------------------------- /erc20/resources-concrete/verification.k: -------------------------------------------------------------------------------- 1 | requires "evm-symbolic.k" 2 | requires "evm-data-map-concrete.k" 3 | requires "edsl.k" 4 | requires "../lemmas.k" 5 | 6 | module VERIFICATION 7 | imports EVM-SYMBOLIC 8 | imports EVM-DATA-MAP-CONCRETE 9 | imports EDSL 10 | imports LEMMAS 11 | 12 | //Rules for #padToWidth with non-regular symbolic arguments. 13 | rule #padToWidth(32, #asByteStack(V)) => #asByteStackInWidth(V, 32) 14 | requires 0 <=Int V andBool V WS 17 | requires #noOverflow(WS) andBool N ==Int #sizeWordStack(WS) 18 | 19 | rule chop ( W0:Int +Int W1:Int ) -Word W1:Int => chop ( W0 ) 20 | requires #rangeUInt(256, W0) andBool #rangeUInt(256, W1) 21 | endmodule 22 | -------------------------------------------------------------------------------- /erc20/solar/Makefile: -------------------------------------------------------------------------------- 1 | KEVM_VERSION_FILE:=../.build/.kevm.rev 2 | KOMPILE_COMMAND=make build-specs K_BIN=$(K_BIN) 3 | override KEVM_BUILD_LAST_DIR=specs 4 | 5 | # Required to have different lemmas dir from non-#buf ERC20 specs. 6 | SPEC_GROUP:=erc20/buf/solar 7 | 8 | DEFINITION_MODULE:=VERIFICATION-SOLAR 9 | 10 | BASEDIR_LEMMAS=$(RESOURCES)/lemmas-buf.md 11 | LOCAL_LEMMAS:=verification-solar.k \ 12 | ../verification.k \ 13 | ../../resources/abstract-semantics-segmented-gas.k \ 14 | ../../resources/evm-symbolic.k \ 15 | ../evm-data-map-symbolic.k \ 16 | solar-abstract-semantics.k 17 | TMPLS:=module-tmpl.k spec-tmpl.k 18 | 19 | KPROVE_OPTS:=--smt-prelude $(abspath $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../resources/evm.smt2) 20 | 21 | SPEC_NAMES:=totalSupply \ 22 | balanceOf \ 23 | allowance \ 24 | approve \ 25 | transfer-success-1 \ 26 | transfer-success-2 \ 27 | transfer-failure-1-a \ 28 | transfer-failure-1-b \ 29 | transfer-failure-2 \ 30 | transferFrom-success-1 \ 31 | transferFrom-success-2 \ 32 | transferFrom-failure-1-a \ 33 | transferFrom-failure-1-b \ 34 | transferFrom-failure-2 35 | 36 | include ../../resources/kprove.mak 37 | -------------------------------------------------------------------------------- /erc20/solar/module-tmpl.k: -------------------------------------------------------------------------------- 1 | requires "abstract-semantics-segmented-gas.k" 2 | requires "solar-abstract-semantics.k" 3 | requires "verification-solar.k" 4 | 5 | module {MODULE}-SPEC 6 | imports ABSTRACT-SEMANTICS-SEGMENTED-GAS 7 | imports SOLAR-ABSTRACT-SEMANTICS 8 | imports VERIFICATION-SOLAR 9 | 10 | {RULES} 11 | 12 | endmodule 13 | -------------------------------------------------------------------------------- /erc20/solar/solar-abstract-semantics.k: -------------------------------------------------------------------------------- 1 | requires "evm-imp-specs.k" 2 | 3 | module SOLAR-ABSTRACT-SEMANTICS 4 | imports EVM-IMP-SPECS 5 | 6 | rule #assume R:Bool => . 7 | ensures R 8 | [trusted] 9 | 10 | endmodule 11 | -------------------------------------------------------------------------------- /erc20/solar/spec-tmpl.k: -------------------------------------------------------------------------------- 1 | // {RULENAME} 2 | rule 3 | {K} 4 | 1 5 | NORMAL 6 | {SCHEDULE} 7 | 8 | 9 | 10 | {OUTPUT} 11 | {STATUSCODE} 12 | _ 13 | _ 14 | _ => _ 15 | 16 | 17 | _ => _ 18 | _ => _ 19 | 20 | _ => _ // contract owner 21 | _ => _ // who called this contract; in the begining, origin // msg.sender 22 | 23 | _ => _ 24 | 25 | 0 26 | .WordStack => _ 27 | .Map => _ 28 | 0 => _ 29 | _ => _ 30 | 0 => _ 31 | {GAS} 32 | 33 | false // NOTE: non-static call 34 | CALL_DEPTH => _ 35 | 36 | 37 | 38 | _ 39 | {LOG} 40 | {REFUND} // TODO: more detail 41 | 42 | 43 | _ 44 | ORIGIN_ID // who fires tx 45 | _ 46 | 47 | _ 48 | _ 49 | _ 50 | _ 51 | _ 52 | _ 53 | _ 54 | _ 55 | _ 56 | _ 57 | _ 58 | _ 59 | _ 60 | _ 61 | _ 62 | 63 | _ 64 | 65 | 66 | 67 | 68 | 0 69 | SetItem(ACCT_ID) _:Set 70 | 71 | 72 | 73 | ACCT_ID 74 | _ 75 | #parseByteStack({CODE}) 76 | {STORAGE} 77 | {ORIGSTORAGE} 78 | _ 79 | 80 | ... 81 | 82 | 83 | _ 84 | _ 85 | _ 86 | 87 | 88 | {COMMANDVARS} 89 | requires #rangeAddress(ACCT_ID) 90 | andBool #rangeAddress(CALLER_ID) 91 | andBool #rangeAddress(ORIGIN_ID) 92 | andBool #range(0 <= CALL_DEPTH < 1020) // providing enough room for 4 calls, including test calls 93 | andBool notBool (ACCT_ID in #precompiledAccounts({SCHEDULE})) 94 | {REQUIRES} 95 | ensures true 96 | {ENSURES} -------------------------------------------------------------------------------- /erc20/solar/verification-solar.k: -------------------------------------------------------------------------------- 1 | requires "verification.k" 2 | requires "evm-imp-specs.k" 3 | 4 | module VERIFICATION-SOLAR 5 | imports VERIFICATION 6 | imports EVM-IMP-SPECS 7 | 8 | rule #sizeWordStack(#padToWidth(N1, _), N2) => N1 +Int N2 9 | 10 | // #buf unification when size is equal 11 | rule #buf(SIZE, DATA1) ==K #buf(SIZE, DATA2) => DATA1 ==K DATA2 12 | //todo is requires needed? Would require lemmas that ensure: rangeUInt(256, select(STORAGE, _)) 13 | /*requires #range(0 <= DATA1 < (2 ^Int (SIZE *Int 8))) 14 | andBool #range(0 <= DATA2 < (2 ^Int (SIZE *Int 8)))*/ 15 | 16 | endmodule 17 | -------------------------------------------------------------------------------- /erc20/spec-tmpl.k: -------------------------------------------------------------------------------- 1 | // {RULENAME} 2 | rule 3 | {K} 4 | 1 5 | NORMAL 6 | {SCHEDULE} 7 | 8 | 9 | 10 | {OUTPUT} 11 | {STATUSCODE} 12 | _ 13 | _ 14 | _ => _ 15 | 16 | 17 | #parseByteStack({CODE}) 18 | #computeValidJumpDests(#parseByteStack({CODE})) 19 | 20 | ACCT_ID // contract owner 21 | CALLER_ID // who called this contract; in the begining, origin // msg.sender 22 | 23 | {CALLDATA} 24 | 25 | 0 26 | .WordStack => _ 27 | .Map => _ 28 | 0 => _ 29 | {GAS} 30 | 0 => _ 31 | _ => _ 32 | 33 | false // NOTE: non-static call 34 | CALL_DEPTH 35 | 36 | 37 | 38 | _ 39 | {LOG} 40 | {REFUND} // TODO: more detail 41 | 42 | 43 | _ 44 | ORIGIN_ID // who fires tx 45 | _ 46 | 47 | _ 48 | _ 49 | _ 50 | _ 51 | _ 52 | _ 53 | _ 54 | _ 55 | _ 56 | _ 57 | _ 58 | _ 59 | _ 60 | _ 61 | _ 62 | 63 | _ 64 | 65 | 66 | 67 | 68 | 0 69 | SetItem(ACCT_ID) _:Set 70 | 71 | 72 | 73 | ACCT_ID 74 | _ 75 | #parseByteStack({CODE}) 76 | {STORAGE} 77 | {ORIGSTORAGE} 78 | _ 79 | 80 | ... 81 | 82 | 83 | _ 84 | _ 85 | _ 86 | 87 | 88 | requires #rangeAddress(ACCT_ID) 89 | andBool #rangeAddress(CALLER_ID) 90 | andBool #rangeAddress(ORIGIN_ID) 91 | andBool #range(0 <= CALL_DEPTH < 1024) 92 | {REQUIRES} 93 | {ENSURES} -------------------------------------------------------------------------------- /erc20/verification.k: -------------------------------------------------------------------------------- 1 | requires "evm-symbolic.k" 2 | requires "evm-data-map-symbolic.k" 3 | requires "edsl.k" 4 | requires "../lemmas-buf.k" 5 | 6 | module VERIFICATION 7 | imports EVM-SYMBOLIC 8 | imports EVM-DATA-MAP-SYMBOLIC 9 | imports EDSL 10 | imports LEMMAS 11 | 12 | rule #buf(N, #asWord(WS)) => WS 13 | requires #noOverflow(WS) andBool N ==Int #sizeByteArray(WS) 14 | 15 | rule chop ( W0:Int +Int W1:Int ) -Word W1:Int => chop ( W0 ) 16 | requires #rangeUInt(256, W0) andBool #rangeUInt(256, W1) 17 | 18 | 19 | // ######################## 20 | // Gas 21 | // ######################## 22 | 23 | rule 0 <=Int X -Int #gas(A, B, C) => true requires #gas(A, B, C) <=Int X 24 | rule X -Int #gas(A, B, C) true requires X (B2 +Int C2) -Int (B1 +Int C1) 27 | 28 | rule 0 <=Int #gas(_, _, _) => true 29 | rule #gas(_, _, _) true 30 | 31 | 32 | // ######################## 33 | // Buffer Reasoning 34 | // ######################## 35 | 36 | rule #noOverflowAux(BUF) => true requires #isBuf(BUF) 37 | rule #noOverflowAux(WS1 ++ WS2) => #noOverflowAux(WS1) andBool #noOverflowAux(WS2) 38 | 39 | // #buf unfolding, for concrete DATA 40 | rule #buf(SIZE, DATA) => #padToWidth(SIZE, #asByteStack(DATA)) requires #range(0 <= DATA < (2 ^Int (SIZE *Int 8))) [concrete] 41 | 42 | // #buf folding, for symbolic DATA - todo test - might apply in too many places 43 | rule #padToWidth(SIZE, #asByteStack(DATA)) => #buf(SIZE, DATA) requires notBool #isConcrete(DATA) 44 | 45 | // ######################## 46 | // Memory Reasoning 47 | // ######################## 48 | 49 | rule store(M, K, select(M, K)) => M 50 | 51 | syntax Bool ::= Map "==IMap" Map [function, smtlib(=)] 52 | syntax Bool ::= Map "==IMap" Map "except" Set [function] 53 | // -------------------------------------------------------- 54 | rule store(M1, K, _) ==IMap M2 except Ks 55 | => M1 ==IMap M2 except Ks 56 | requires K in Ks 57 | 58 | rule M1 ==IMap store(M2, K, _) except Ks 59 | => M1 ==IMap M2 except Ks 60 | requires K in Ks 61 | 62 | rule M1 ==IMap M2 except _ => true 63 | requires M1 ==K M2 // structural equality 64 | 65 | syntax Set ::= keys(Map) [function] 66 | // ----------------------------------- 67 | rule K1 in keys(store(M, K2, _)) => true requires K1 ==Int K2 68 | rule K1 in keys(store(M, K2, _)) => K1 in keys(M) requires K1 =/=Int K2 69 | 70 | //Reduces IMaps where multiple entries share the same key 71 | rule store(store(M, K0, V0), K1, V1) => store(M, K0, V1) 72 | requires K0 ==Int K1 73 | 74 | rule store(store(M, K0, V0), K1, V1) => store(store(M, K1, V1), K0, V0) 75 | requires K0 =/=Int K1 andBool K1 in keys(M) 76 | 77 | rule notBool( hash2(K1,V1) ==K hash2(K2,V2) ) => K1 =/=Int K2 orBool V1 =/=Int V2 78 | 79 | rule A ==K hash2(K,V) => hash2(K,V) ==K A 80 | requires #isConcrete(A) 81 | 82 | //Assumption of non-collision between hashes and small constants that likely represent memory addresses or offsets. 83 | rule notBool( hash2(_,_) ==K A ) => true 84 | requires #isConcrete(A) andBool A <=Int 20 85 | 86 | // ######################## 87 | // Arithmetic 88 | // ######################## 89 | 90 | rule A -Int B +Int B => A 91 | rule A +Int B -Int B => A 92 | rule A +Int B -Int A => B 93 | rule A +Int (B -Int A) => B 94 | 95 | endmodule 96 | -------------------------------------------------------------------------------- /erc20/vyper/.build/.kevm.rev: -------------------------------------------------------------------------------- 1 | 27ab1d7e6114e13bc31294d99cafd5d6d0ce7131 2 | -------------------------------------------------------------------------------- /erc20/vyper/ERC20.v.bytes: -------------------------------------------------------------------------------- 1 | 0x600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a05263d0e30db06000511415610168573460008112585761014052336101605261016051600060c052602060c02001546101405161016051600060c052602060c020015401116101405115176100e657600080fd5b6101405161016051600060c052602060c02001540161016051600060c052602060c020015560025461014051600254011161014051151761012657600080fd5b610140516002540160025561014051610180526101605160007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020610180a3005b632e1a7d4d6000511415610260576020600461014037341561018957600080fd5b33610160526101405161016051600060c052602060c020015410156101ad57600080fd5b6101405161016051600060c052602060c02001540361016051600060c052602060c02001556101405160025410156101e457600080fd5b61014051600254036002556000600060006000600160605161014051806040519013585780919012585702610160516000f161021f57600080fd5b61014051610180526000610160517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020610180a3600160005260206000f3005b6318160ddd600051141561028657341561027957600080fd5b60025460005260206000f3005b6370a0823160005114156102cd57602060046101403734156102a757600080fd5b60043560205181101558575061014051600060c052602060c020015460005260206000f3005b63a9059cbb60005114156103e057604060046101403734156102ee57600080fd5b60043560205181101558575033610180526101605161018051600060c052602060c0200154101561031e57600080fd5b6101605161018051600060c052602060c02001540361018051600060c052602060c020015561014051600060c052602060c02001546101605161014051600060c052602060c0200154011161016051151761037857600080fd5b6101605161014051600060c052602060c02001540161014051600060c052602060c0200155610160516101a05261014051610180517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60206101a0a3600160005260206000f3005b6323b872dd6000511415610559576060600461014037341561040157600080fd5b600435602051811015585750602435602051811015585750336101a0526101a05161014051600160c052602060c0200160c052602060c02001546101c0526101805161014051600060c052602060c0200154101561045e57600080fd5b6101805161014051600060c052602060c02001540361014051600060c052602060c020015561016051600060c052602060c02001546101805161016051600060c052602060c020015401116101805115176104b857600080fd5b6101805161016051600060c052602060c02001540161016051600060c052602060c0200155610180516101c05110156104f057600080fd5b610180516101c051036101a05161014051600160c052602060c0200160c052602060c0200155610180516101e05261016051610140517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60206101e0a3600160005260206000f3005b63095ea7b360005114156105ef576040600461014037341561057a57600080fd5b6004356020518110155857503361018052610160516101405161018051600160c052602060c0200160c052602060c0200155610160516101a05261014051610180517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560206101a0a3600160005260206000f3005b63dd62ed3e600051141561064f576040600461014037341561061057600080fd5b6004356020518110155857506024356020518110155857506101605161014051600160c052602060c0200160c052602060c020015460005260206000f3005b 2 | -------------------------------------------------------------------------------- /erc20/vyper/ERC20.v.py: -------------------------------------------------------------------------------- 1 | # Solidity-Compatible EIP20/ERC20 Token 2 | # Implements https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md 3 | # Author: Phil Daian 4 | 5 | # The use of the num256 datatype as in this token is not 6 | # recommended, as it can pose security risks. 7 | 8 | # This token is intended as a proof of concept towards 9 | # language interoperability and not for production use. 10 | 11 | # Events issued by the contract 12 | Transfer: __log__({_from: indexed(address), _to: indexed(address), _value: num256}) 13 | Approval: __log__({_owner: indexed(address), _spender: indexed(address), _value: num256}) 14 | 15 | balances: num256[address] 16 | allowances: (num256[address])[address] 17 | num_issued: num256 18 | 19 | @public 20 | @payable 21 | def deposit(): 22 | _value = as_num256(msg.value) 23 | _sender = msg.sender 24 | self.balances[_sender] = num256_add(self.balances[_sender], _value) 25 | self.num_issued = num256_add(self.num_issued, _value) 26 | # Fire deposit event as transfer from 0x0 27 | log.Transfer(0x0000000000000000000000000000000000000000, _sender, _value) 28 | 29 | @public 30 | def withdraw(_value : num256) -> bool: 31 | _sender = msg.sender 32 | # Make sure sufficient funds are present, op will not underflow supply 33 | # implicitly through overflow protection 34 | self.balances[_sender] = num256_sub(self.balances[_sender], _value) 35 | self.num_issued = num256_sub(self.num_issued, _value) 36 | send(_sender, as_wei_value(as_num128(_value), wei)) 37 | # Fire withdraw event as transfer to 0x0 38 | log.Transfer(_sender, 0x0000000000000000000000000000000000000000, _value) 39 | return true 40 | 41 | @public 42 | @constant 43 | def totalSupply() -> num256: 44 | return self.num_issued 45 | 46 | @public 47 | @constant 48 | def balanceOf(_owner : address) -> num256: 49 | return self.balances[_owner] 50 | 51 | @public 52 | def transfer(_to : address, _value : num256) -> bool: 53 | _sender = msg.sender 54 | # Make sure sufficient funds are present implicitly through overflow protection 55 | self.balances[_sender] = num256_sub(self.balances[_sender], _value) 56 | self.balances[_to] = num256_add(self.balances[_to], _value) 57 | # Fire transfer event 58 | log.Transfer(_sender, _to, _value) 59 | return true 60 | 61 | @public 62 | def transferFrom(_from : address, _to : address, _value : num256) -> bool: 63 | _sender = msg.sender 64 | allowance = self.allowances[_from][_sender] 65 | # Make sure sufficient funds/allowance are present implicitly through overflow protection 66 | self.balances[_from] = num256_sub(self.balances[_from], _value) 67 | self.balances[_to] = num256_add(self.balances[_to], _value) 68 | self.allowances[_from][_sender] = num256_sub(allowance, _value) 69 | # Fire transfer event 70 | log.Transfer(_from, _to, _value) 71 | return true 72 | 73 | @public 74 | def approve(_spender : address, _value : num256) -> bool: 75 | _sender = msg.sender 76 | self.allowances[_sender][_spender] = _value 77 | # Fire approval event 78 | log.Approval(_sender, _spender, _value) 79 | return true 80 | 81 | @public 82 | @constant 83 | def allowance(_owner : address, _spender : address) -> num256: 84 | return self.allowances[_owner][_spender] 85 | 86 | -------------------------------------------------------------------------------- /erc20/vyper/Makefile: -------------------------------------------------------------------------------- 1 | # Bytecode compiled with old Vyper. Needs KEVM version before Vyper storage layout fix. 2 | KEVM_VERSION_FILE:=.build/.kevm.rev 3 | 4 | # Required to have different lemmas dir from non-#buf ERC20 specs. 5 | SPEC_GROUP:=erc20/vyper/vyper 6 | 7 | DEFINITION_MODULE:=VYPER-VERIFICATION 8 | 9 | BASEDIR_LEMMAS=lemmas-buf.md 10 | # We need gnosis version of abstract-semantics-segmented-gas.k because we use an older KEVM. 11 | LOCAL_LEMMAS:=vyper-verification.k \ 12 | ../verification.k \ 13 | ../../gnosis/abstract-semantics-segmented-gas.k \ 14 | ../../resources/evm-symbolic.k \ 15 | ../../resources/evm-data-map-symbolic.k \ 16 | ../../resources/not-KLabel.k 17 | TMPLS:=module-tmpl.k spec-tmpl.k 18 | 19 | KPROVE_OPTS=--smt-prelude $(RESOURCES)/evm.smt2 20 | 21 | SPEC_NAMES:=totalSupply \ 22 | balanceOf \ 23 | allowance \ 24 | approve \ 25 | transfer-success-1 \ 26 | transfer-success-2 \ 27 | transfer-failure-1 \ 28 | transfer-failure-2 \ 29 | transferFrom-success-1 \ 30 | transferFrom-success-2 \ 31 | transferFrom-failure-1 \ 32 | transferFrom-failure-2 33 | 34 | include ../../resources/kprove.mak 35 | -------------------------------------------------------------------------------- /erc20/vyper/module-tmpl.k: -------------------------------------------------------------------------------- 1 | requires "abstract-semantics-segmented-gas.k" 2 | requires "vyper-verification.k" 3 | 4 | // Custom module-tmpl needed to import VYPER-VERIFICATION, in turn needed to import NOT-KLABEL 5 | module {MODULE}-SPEC 6 | imports ABSTRACT-SEMANTICS-SEGMENTED-GAS 7 | imports VYPER-VERIFICATION 8 | 9 | {RULES} 10 | 11 | endmodule 12 | -------------------------------------------------------------------------------- /erc20/vyper/spec-tmpl.k: -------------------------------------------------------------------------------- 1 | // {RULENAME} 2 | rule 3 | {K} 4 | 1 5 | NORMAL 6 | {SCHEDULE} 7 | 8 | 9 | 10 | {OUTPUT} 11 | {STATUSCODE} 12 | _ 13 | _ 14 | _ => _ 15 | 16 | 17 | #parseByteStack({CODE}) 18 | #computeValidJumpDests(#parseByteStack({CODE})) 19 | 20 | ACCT_ID // contract owner 21 | CALLER_ID // who called this contract; in the begining, origin // msg.sender 22 | 23 | {CALLDATA} 24 | 25 | 0 26 | .WordStack => _ 27 | .Map => _ 28 | 0 => _ 29 | {GAS} 30 | 0 => _ 31 | _ => _ 32 | 33 | false // NOTE: non-static call 34 | CALL_DEPTH 35 | 36 | 37 | 38 | _ 39 | {LOG} 40 | {REFUND} // TODO: more detail 41 | 42 | 43 | _ 44 | ORIGIN_ID // who fires tx 45 | _ 46 | 47 | _ 48 | _ 49 | _ 50 | _ 51 | _ 52 | _ 53 | _ 54 | _ 55 | _ 56 | _ 57 | _ 58 | _ 59 | _ 60 | _ 61 | _ 62 | 63 | _ 64 | 65 | 66 | 67 | 68 | SetItem(ACCT_ID) _:Set 69 | 70 | 71 | 72 | ACCT_ID 73 | _ 74 | #parseByteStack({CODE}) 75 | {STORAGE} 76 | {ORIGSTORAGE} 77 | _ 78 | 79 | ... 80 | 81 | 82 | _ 83 | _ 84 | _ 85 | 86 | 87 | requires #rangeAddress(ACCT_ID) 88 | andBool #rangeAddress(CALLER_ID) 89 | andBool #rangeAddress(ORIGIN_ID) 90 | andBool #range(0 <= CALL_DEPTH < 1024) 91 | {REQUIRES} 92 | {ENSURES} -------------------------------------------------------------------------------- /erc20/vyper/vyper-verification.k: -------------------------------------------------------------------------------- 1 | requires "verification.k" 2 | requires "not-KLabel.k" 3 | 4 | module VYPER-VERIFICATION [symbolic] 5 | imports VERIFICATION 6 | imports NOT-KLABEL 7 | endmodule 8 | -------------------------------------------------------------------------------- /erc20/zeppelin/Makefile: -------------------------------------------------------------------------------- 1 | KEVM_VERSION_FILE:=../.build/.kevm.rev 2 | 3 | # Required to have different lemmas dir from non-#buf ERC20 specs. 4 | SPEC_GROUP:=erc20/buf/zeppelin 5 | 6 | BASEDIR_LEMMAS=$(RESOURCES)/lemmas-buf.md 7 | LOCAL_LEMMAS:=../verification.k \ 8 | ../../resources/abstract-semantics-segmented-gas.k \ 9 | ../../resources/evm-symbolic.k \ 10 | ../evm-data-map-symbolic.k 11 | TMPLS:=../module-tmpl.k ../spec-tmpl.k 12 | 13 | KPROVE_OPTS=--smt-prelude $(RESOURCES)/evm.smt2 14 | 15 | SPEC_NAMES:=totalSupply \ 16 | balanceOf \ 17 | allowance \ 18 | approve \ 19 | transfer-success-1 \ 20 | transfer-success-2 \ 21 | transfer-failure-1-a \ 22 | transfer-failure-1-b \ 23 | transfer-failure-2 \ 24 | transferFrom-success-1 \ 25 | transferFrom-success-2 \ 26 | transferFrom-failure-1-a \ 27 | transferFrom-failure-1-b \ 28 | transferFrom-failure-2 29 | 30 | include ../../resources/kprove.mak 31 | -------------------------------------------------------------------------------- /erc20/zeppelin/StandardToken.inlined.gist: -------------------------------------------------------------------------------- 1 | https://gist.github.com/anonymous/329a61e60ff35a75fd74865df1010fcd 2 | -------------------------------------------------------------------------------- /erc20/zeppelin/spec-diff.patch: -------------------------------------------------------------------------------- 1 | @@ -81,6 +81,7 @@ 2 | andBool CALLER_ID =/=Int TO_ID 3 | andBool VALUE <=Int BAL_FROM 4 | andBool BAL_TO +Int VALUE #exception 17 | @@ -103,7 +105,8 @@ 18 | +requires: 19 | andBool CALLER_ID =/=Int TO_ID 20 | andBool ( VALUE >Int BAL_FROM 21 | - orBool BAL_TO +Int VALUE >=Int (2 ^Int 256) ) 22 | + orBool BAL_TO +Int VALUE >=Int (2 ^Int 256) 23 | + orBool TO_ID ==Int 0 ) 24 | 25 | [transfer-failure-2] 26 | storage: 27 | @@ -111,7 +114,8 @@ 28 | _:Map 29 | +requires: 30 | andBool CALLER_ID ==Int TO_ID 31 | - andBool VALUE >Int BAL_FROM 32 | + andBool ( VALUE >Int BAL_FROM 33 | + orBool TO_ID ==Int 0 ) 34 | 35 | [transferFrom] 36 | callData: #abiCallData("transferFrom", #address(FROM_ID), #address(TO_ID), #uint256(VALUE)) 37 | @@ -141,6 +145,7 @@ 38 | andBool VALUE <=Int BAL_FROM 39 | andBool BAL_TO +Int VALUE #exception 53 | @@ -167,7 +173,8 @@ 54 | andBool FROM_ID =/=Int TO_ID 55 | andBool ( VALUE >Int BAL_FROM 56 | orBool BAL_TO +Int VALUE >=Int (2 ^Int 256) 57 | - orBool VALUE >Int ALLOW ) 58 | + orBool VALUE >Int ALLOW 59 | + orBool TO_ID ==Int 0 ) 60 | 61 | [transferFrom-failure-2] 62 | storage: 63 | @@ -177,12 +184,13 @@ 64 | +requires: 65 | andBool FROM_ID ==Int TO_ID 66 | andBool ( VALUE >Int BAL_FROM 67 | - orBool VALUE >Int ALLOW ) 68 | + orBool VALUE >Int ALLOW 69 | + orBool TO_ID ==Int 0 ) 70 | -------------------------------------------------------------------------------- /gnosis/.build/.kevm.rev: -------------------------------------------------------------------------------- 1 | 27ab1d7e6114e13bc31294d99cafd5d6d0ce7131 2 | -------------------------------------------------------------------------------- /gnosis/GnosisSafe_RuntimeVerification.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/verified-smart-contracts/e61ef57de99d07d7182436490f152a14621c5a82/gnosis/GnosisSafe_RuntimeVerification.pdf -------------------------------------------------------------------------------- /gnosis/GnosisSafe_RuntimeVerification_Audit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/verified-smart-contracts/e61ef57de99d07d7182436490f152a14621c5a82/gnosis/GnosisSafe_RuntimeVerification_Audit.pdf -------------------------------------------------------------------------------- /gnosis/abstract-semantics-segmented-gas.k: -------------------------------------------------------------------------------- 1 | requires "evm-symbolic.k" 2 | requires "not-KLabel.k" 3 | 4 | //Older version that uses #notKLabel 5 | module ABSTRACT-SEMANTICS-SEGMENTED-GAS 6 | imports EVM 7 | imports EVM-SYMBOLIC 8 | imports NOT-KLABEL 9 | 10 | // to avoid unnecessary case analyses 11 | rule LT W0 W1 => bool2Word(W0 #push ... [trusted] 12 | rule GT W0 W1 => bool2Word(W0 >Int W1) ~> #push ... [trusted] 13 | rule EQ W0 W1 => bool2Word(W0 ==Int W1) ~> #push ... [trusted] 14 | rule ISZERO W => bool2Word(W ==Int 0 ) ~> #push ... [trusted] 15 | 16 | // ######################## 17 | // Segmented gas representatioon - #gas construct 18 | // ######################## 19 | 20 | // accumulate the gas cost and never run out of gas 21 | rule G ~> #deductGas => . ... 22 | #gas(INITGAS, NONMEM, MEM) => #gas(INITGAS, NONMEM +Int G, MEM) 23 | _ => #gas(INITGAS, NONMEM, MEM) 24 | requires #notKLabel(G, "#symCmem") 25 | [trusted, matching(#gas)] 26 | 27 | rule #symCmem(MEM') ~> #deductGas => . ... 28 | #gas(INITGAS, NONMEM, MEM) => #gas(INITGAS, NONMEM, MEM +Int MEM') 29 | _ => #gas(INITGAS, NONMEM, MEM) 30 | [trusted, matching(#symCmem,#gas)] 31 | 32 | //If G is not explicitly typed, it will be typed as G:K. This leads to intermittent SPEC ERROR below, 33 | // in multi-threaded environment, on appliation of this rule. 34 | // `java.lang.AssertionError: disjunctions are not supported by SMT translation` 35 | // Issue cause: contains 2 terms `#deductGas`, so for G:K, the rule can match in 2 ways. Observed with in hkg-erc20. 36 | rule G:KItem ~> #deductGas ... 37 | INITGAS => #gas(INITGAS, 0, 0) 38 | requires #notKLabel(INITGAS, "#gas") 39 | [trusted] 40 | 41 | rule MU':Int ~> #deductMemory => #symCmem(Cmem(SCHED, MU') -Int Cmem(SCHED, MU)) ~> #deductGas ... 42 | MU => MU' SCHED 43 | [trusted] 44 | endmodule 45 | -------------------------------------------------------------------------------- /gnosis/bmc/Makefile: -------------------------------------------------------------------------------- 1 | KEVM_VERSION_FILE:=../.build/.kevm.rev 2 | 3 | LOCAL_LEMMAS:=../abstract-semantics.k ../verification.k ../abstract-semantics-segmented-gas.k ../../resources/not-KLabel.k 4 | TMPLS:=../module-tmpl.k ../spec-tmpl.k 5 | 6 | KPROVE_OPTS:=--smt-prelude $(abspath $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../evm.smt2) 7 | 8 | SPEC_NAMES:=encodeTransactionData \ 9 | signatureSplit \ 10 | checkSignatures-thres-too-large \ 11 | checkSignatures-thres-1-sig-v2-ec0 \ 12 | checkSignatures-thres-1-sig-v2-not-ec0-success \ 13 | checkSignatures-thres-1-sig-v2-not-ec0-notOwner \ 14 | checkSignatures-thres-2-sig-v2-ec0 \ 15 | checkSignatures-thres-2-sig-v2-o0-eq-o1 16 | 17 | # FIXME: 18 | # checkSignatures-thres-1-sig-v0 19 | # checkSignatures-thres-2-sig-v2-o0-neq-o1-success 20 | # checkSignatures-thres-2-sig-v2-o0-neq-o1-failure 21 | 22 | include ../../resources/kprove.mak 23 | -------------------------------------------------------------------------------- /gnosis/bmc/generated-external-contract/ExternalContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | contract ExternalContract { 4 | 5 | function isValidSignature( 6 | bytes calldata _data, 7 | bytes calldata _signature) 8 | external 9 | returns (bool isValid) 10 | { 11 | isValid = false; 12 | } 13 | } -------------------------------------------------------------------------------- /gnosis/bmc/generated-external-contract/gnosis-testing-ExternalContract.hex: -------------------------------------------------------------------------------- 1 | 2 | ======= ExternalContract.sol:ExternalContract ======= 3 | Binary of the runtime part: 4 | 608060405234801561001057600080fd5b5060043610610048576000357c01000000000000000000000000000000000000000000000000000000009004806320c13b0b1461004d575b600080fd5b6101196004803603604081101561006357600080fd5b810190808035906020019064010000000081111561008057600080fd5b82018360208201111561009257600080fd5b803590602001918460018302840111640100000000831117156100b457600080fd5b9091929391929390803590602001906401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b9091929391929390505050610133565b604051808215151515815260200191505060405180910390f35b600080905094935050505056fea165627a7a72305820e0f7eff099fa7c3378fadb78e36eb0155b2a913a00f5eefceec8242c88e84ca10029 -------------------------------------------------------------------------------- /gnosis/evm.smt2: -------------------------------------------------------------------------------- 1 | ; (set-option :auto-config false) 2 | ; (set-option :smt.mbqi false) 3 | ; (set-option :smt.array.extensional false) 4 | 5 | ; int extra 6 | (define-fun int_max ((x Int) (y Int)) Int (ite (< x y) y x)) 7 | (define-fun int_min ((x Int) (y Int)) Int (ite (< x y) x y)) 8 | (define-fun int_abs ((x Int)) Int (ite (< x 0) (- 0 x) x)) 9 | 10 | ; bool to int 11 | (define-fun smt_bool2int ((b Bool)) Int (ite b 1 0)) 12 | 13 | ; IMap 14 | (define-sort IMap () (Array Int Int)) 15 | (define-fun emptyIMap () IMap ((as const IMap) 0)) 16 | 17 | ; ceil32 18 | (define-fun ceil32 ((x Int)) Int ( * ( div ( + x 31 ) 32 ) 32 ) ) 19 | -------------------------------------------------------------------------------- /gnosis/generated/gnosis-Proxy-0.1.0.hex: -------------------------------------------------------------------------------- 1 | 2 | ======= contracts/proxies/Proxy.sol:Proxy ======= 3 | Binary of the runtime part: 4 | 60806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680634555d5c91461008b5780635c60da1b146100b6575b73ffffffffffffffffffffffffffffffffffffffff600054163660008037600080366000845af43d6000803e6000811415610086573d6000fd5b3d6000f35b34801561009757600080fd5b506100a061010d565b6040518082815260200191505060405180910390f35b3480156100c257600080fd5b506100cb610116565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60006002905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690509056fea165627a7a723058201cddd95839fb6a2721e9db6df2726cacc48f77a2b18ba97008f236afad1ada7f0029 5 | -------------------------------------------------------------------------------- /gnosis/generated/solidity compilation instructions.txt: -------------------------------------------------------------------------------- 1 | Solidity version: 0.5.1-develop.2018.11.29+commit.f6d01323.Linux.g++ 2 | Gnosis version: https://github.com/denis-bogdanas/safe-contracts 3 | branch `rv` 4 | At the moment it is v0.1.0 with some functions marked public. 5 | 6 | Instructions to produce hex files: 7 | 8 | $ cd 9 | $ solc --bin-runtime contracts/proxies/Proxy.sol > gnosis-Proxy-0.1.0.hex 10 | $ solc --bin-runtime contracts/GnosisSafe.sol > gnosis-GnosisSafe-0.1.0.hex 11 | 12 | When compiling Solidity code which contains multiple contracts and libraries, the output bytecode will be split in multiple strings, one for each contract/library. 13 | If one of the contracts inherits the others, then its bytecode will contain the bytecode of the inherited contracts and libraries as well. 14 | 15 | Resulting files are bigger than .hex files in this repo. They contain the bytecode for multiple solidity classes. 16 | Hex files on this repo were cleared up. They only contain the fragment that was used in gnosis-spec.ini 17 | 18 | To generate .evm files: 19 | Use --asm option instead of --bin-runtime 20 | -------------------------------------------------------------------------------- /gnosis/module-tmpl.k: -------------------------------------------------------------------------------- 1 | requires "abstract-semantics.k" 2 | requires "verification.k" 3 | 4 | module {MODULE}-SPEC 5 | imports ABSTRACT-SEMANTICS 6 | imports VERIFICATION 7 | 8 | {RULES} 9 | 10 | endmodule 11 | -------------------------------------------------------------------------------- /gnosis/old/old-issues.md: -------------------------------------------------------------------------------- 1 | ## malicious library 2 | Since this scenario requires correct set of signatures, 3 | the risk is reduced if the library code is verified to be safe. 4 | ```solidity 5 | contract C { 6 | function foo() { 7 | owners[SENTINEL_OWNERS] = SENTINEL_OWNERS; 8 | } 9 | function bar() { 10 | call(to=proxy, data=removeOwner(..)); 11 | } 12 | } 13 | ``` 14 | Contract C deployed at address `a`. 15 | ### 1. executor calls `execTransactionAndPaySubmitter(to = a, data = C.foo, operation = DelegateCall, correct signatures)` 16 | 1. fallback function `delegatecall`s `execTransactionAndPaySubmitter`. 17 | * `this`: Proxy 18 | * `msg.sender`: executor 19 | 2. `execTransactionAndPaySubmitter` calls `execute` and then `executeDelegateCall` internally. 20 | * `this`: Proxy 21 | * `msg.sender`: executor 22 | 3. `executeDelegateCall` `delegatecall`s `C.foo` at address `a` 23 | * `this`: Proxy 24 | * `msg.sender`: executor 25 | 4. storage of the Proxy is modified. 26 | 27 | ### 2.executor calls `execTransactionAndPaySubmitter(data = C.foo,...)` 28 | 1. ~3. same as above. 29 | 4. `C.bar` `call`s `removeOwner` to proxy 30 | * `this`: proxy 31 | * `msg.sender`: proxy 32 | * ==> `authorized` 33 | -------------------------------------------------------------------------------- /gnosis/test/ApiTest.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.0; 2 | 3 | 4 | /// @title Enum - Collection of enums 5 | /// @author Richard Meissner - 6 | contract ApiTest { 7 | enum Operation { 8 | Call, 9 | DelegateCall, 10 | Create 11 | } 12 | 13 | bytes32 public constant SAFE_TX_TYPEHASH = 0x14d461bc7412367e924637b363c7bf29b8f47e2f84869f4426e5633d8af47b20; 14 | bytes32 public domainSeparator; 15 | 16 | //same set of arguments as encodeTransactionData 17 | function testAbiEncodeAndKeccak( 18 | address to, 19 | uint256 value, 20 | bytes memory data, 21 | Operation operation, 22 | uint256 safeTxGas, 23 | uint256 dataGas, 24 | uint256 gasPrice, 25 | address gasToken, 26 | address refundReceiver, 27 | uint256 _nonce 28 | ) 29 | public 30 | pure 31 | returns (bytes memory) 32 | { 33 | return abi.encode(SAFE_TX_TYPEHASH, to, value, keccak256(data), operation, safeTxGas, dataGas, gasPrice, gasToken, refundReceiver, _nonce); 34 | } 35 | 36 | function testAbiEncode( 37 | address to, 38 | uint256 value, 39 | bytes32 keccakOut, 40 | Operation operation, 41 | uint256 safeTxGas, 42 | uint256 dataGas, 43 | uint256 gasPrice, 44 | address gasToken, 45 | address refundReceiver, 46 | uint256 _nonce 47 | ) 48 | public 49 | pure 50 | returns (bytes memory) 51 | { 52 | return abi.encode(SAFE_TX_TYPEHASH, to, value, keccakOut, operation, safeTxGas, dataGas, gasPrice, gasToken, refundReceiver, _nonce); 53 | } 54 | 55 | function testKeccak(bytes memory data) 56 | public 57 | pure 58 | returns (bytes32) 59 | { 60 | return keccak256(data); 61 | } 62 | 63 | function testAbiEncodePacked(bytes32 safeTxHash) 64 | public 65 | view 66 | returns (bytes memory) 67 | { 68 | return abi.encodePacked(byte(0x19), byte(0x01), domainSeparator, safeTxHash); 69 | } 70 | 71 | function testEcrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) 72 | public 73 | pure 74 | returns (address) 75 | { 76 | return ecrecover(hash, v, r, s); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /gnosis/test/Makefile: -------------------------------------------------------------------------------- 1 | KEVM_VERSION_FILE:=../.build/.kevm.rev 2 | 3 | LOCAL_LEMMAS:=../verification.k \ 4 | ../abstract-semantics.k \ 5 | ../abstract-semantics-segmented-gas.k \ 6 | ../../resources/evm-symbolic.k \ 7 | ../../resources/evm-data-map-symbolic.k \ 8 | ../../resources/ecrec-symbolic.k \ 9 | ../../resources/not-KLabel.k 10 | TMPLS:=../module-tmpl.k ../spec-tmpl.k 11 | 12 | KPROVE_OPTS:=--smt-prelude $(abspath $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../evm.smt2) 13 | 14 | SPEC_NAMES:=testKeccak-1 \ 15 | testKeccak-2 \ 16 | testAbiEncode \ 17 | testAbiEncode-AndKeccak-1 \ 18 | testAbiEncode-AndKeccak-2 \ 19 | testAbiEncodePacked \ 20 | testEcrecover-non-empty \ 21 | testEcrecover-empty 22 | 23 | include ../../resources/kprove.mak 24 | -------------------------------------------------------------------------------- /k-test/KTest.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.24; 2 | 3 | 4 | /// Contracts for testing kprove reasoning engine. 5 | contract KTest { 6 | 7 | function ecrecImplication(address a1, bytes32 p1, uint8 a2v, bytes32 p3, bytes32 p4, address a3) 8 | public 9 | pure 10 | returns (bool) 11 | { 12 | address a2 = ecrecover(p1, a2v, p3, p4); 13 | return a1 < a2 && a2 < a3; 14 | } 15 | 16 | function ecrecConstraint(address a1, bytes32 p1, uint8 a2v, bytes32 p3, bytes32 p4, address a3) 17 | public 18 | pure 19 | returns (bool) 20 | { 21 | address a2 = ecrecover(p1, a2v, p3, p4); 22 | if (a1 < a2 && a2 < a3) { 23 | return true; 24 | } 25 | return false; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /k-test/Makefile: -------------------------------------------------------------------------------- 1 | #BUILD_DIR:=../erc20/.build 2 | 3 | # verification.k is required to import evm-symbolic.k 4 | LOCAL_LEMMAS:=verification.k \ 5 | abstract-semantics.k \ 6 | ../resources/abstract-semantics-segmented-gas.k \ 7 | ../resources/evm-symbolic.k \ 8 | ../resources/evm-data-map-concrete.k \ 9 | ../resources/ecrec-symbolic.k 10 | 11 | # Just to have the simplest initial config 12 | TMPLS:=../gnosis/module-tmpl.k spec-tmpl.k 13 | 14 | MAKEFILE_PATH := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) 15 | KPROVE_OPTS:=--smt-prelude $(MAKEFILE_PATH)/smt-prelude.smt2 16 | 17 | SPEC_NAMES:=ecrecT-false-implication \ 18 | ecrecT-false-constraint \ 19 | rhsOnlyVar \ 20 | test-getKLabelString 21 | 22 | include ../resources/kprove.mak 23 | -------------------------------------------------------------------------------- /k-test/abstract-semantics.k: -------------------------------------------------------------------------------- 1 | requires "abstract-semantics-segmented-gas.k" 2 | requires "ecrec-symbolic.k" 3 | 4 | module ABSTRACT-SEMANTICS 5 | imports ABSTRACT-SEMANTICS-SEGMENTED-GAS 6 | imports ECREC-SYMBOLIC 7 | endmodule 8 | -------------------------------------------------------------------------------- /k-test/smt-prelude.smt2: -------------------------------------------------------------------------------- 1 | (set-option :auto-config false) 2 | (set-option :smt.mbqi true) 3 | -------------------------------------------------------------------------------- /k-test/spec-tmpl.k: -------------------------------------------------------------------------------- 1 | // {RULENAME} 2 | rule 3 | {K} 4 | 1 5 | NORMAL 6 | {SCHEDULE} 7 | 8 | 9 | 10 | {OUTPUT} 11 | {STATUSCODE} 12 | _ 13 | _ 14 | _ => _ 15 | 16 | 17 | #parseByteStack({CODE}) 18 | #computeValidJumpDests(#parseByteStack({CODE})) 19 | 20 | ACCT_ID // contract owner 21 | CALLER_ID // who called this contract; in the begining, origin // msg.sender 22 | 23 | {CALLDATA} 24 | 25 | 0 26 | .WordStack => _ 27 | .Map => _ 28 | 0 => _ 29 | {GAS} 30 | 0 => _ 31 | _ => _ 32 | 33 | false // NOTE: non-static call 34 | {CALLDEPTH} 35 | 36 | 37 | 38 | _ 39 | {LOG} 40 | {REFUND} // TODO: more detail 41 | 42 | 43 | _ 44 | ORIGIN_ID // who fires tx 45 | _ 46 | 47 | _ 48 | _ 49 | _ 50 | _ 51 | _ 52 | _ 53 | _ 54 | _ 55 | _ 56 | _ 57 | _ 58 | _ 59 | _ 60 | _ 61 | _ 62 | 63 | _ 64 | 65 | 66 | 67 | 68 | 0 69 | SetItem(ACCT_ID) SetItem(1) _:Set 70 | 71 | 72 | 73 | ACCT_ID 74 | {BALANCE} 75 | #parseByteStack({CODE}) 76 | {STORAGE} 77 | {ORIGSTORAGE} 78 | _ 79 | 80 | 81 | // precompiled account for ECCREC 82 | 1 83 | 0 84 | .WordStack 85 | .Map 86 | .Map 87 | 0 88 | 89 | // ... // TODO: fix 90 | 91 | 92 | _ 93 | _ 94 | _ 95 | 96 | 97 | requires 0 <=Int ACCT_ID andBool ACCT_ID #sizeWordStack(WS, 0) +Int N SIZELIMIT SIZELIMIT #sizeWordStack(WS, 0) +Int N <=Int SIZE requires N =/=Int 0 17 | 18 | //Rules for #padToWidth with non-regular symbolic arguments. 19 | rule #padToWidth(32, #asByteStack(V)) => #asByteStackInWidth(V, 32) 20 | requires 0 <=Int V andBool V WS 23 | requires #noOverflow(WS) andBool N ==Int #sizeWordStack(WS) 24 | 25 | rule X modInt Y => X 26 | requires 0 <=Int X andBool X chop ( W0 ) 29 | requires #rangeUInt(256, W0) andBool #rangeUInt(256, W1) 30 | 31 | // The number below is equal to: (2^256 - 1) - (2^160 - 1), which in hex would be graphically 32 | // f...f (24 times) ++ 0...0 (40 times). An Ethereum address has at most 40 hex digits. 33 | // It follow when we bit-wise AND the two numbers, the result will always be 0. 34 | 35 | rule 115792089237316195423570985007226406215939081747436879206741300988257197096960 &Int X:Int => 0 36 | requires #rangeAddress(X) 37 | endmodule 38 | -------------------------------------------------------------------------------- /resources/Makefile: -------------------------------------------------------------------------------- 1 | SPEC_GROUP:=examples 2 | # mock non-empty value 3 | SPEC_INI:=.mock.ini 4 | 5 | KPROVE_OPTS:=--smt-prelude $(abspath $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/evm.smt2) 6 | 7 | SPEC_NAMES:=sum-to-n 8 | 9 | LOCAL_LEMMAS:= 10 | TMPLS:= 11 | 12 | include kprove.mak 13 | 14 | # non-standard spec generation 15 | $(SPECS_DIR)/$(SPEC_GROUP)/sum-to-n-spec.k: $(RESOURCES)/sum-to-n.md $(TANGLER) $(LEMMAS) 16 | pandoc --from markdown --to "$(TANGLER)" --metadata="code:.sum-to-n" $< > $@ 17 | -------------------------------------------------------------------------------- /resources/abstract-semantics-direct-gas.k: -------------------------------------------------------------------------------- 1 | requires "evm-direct-gas.k" 2 | 3 | module ABSTRACT-SEMANTICS-DIRECT-GAS 4 | imports EVM 5 | imports EVM-DIRECT-GAS 6 | 7 | // to avoid unnecessary case analyses 8 | rule LT W0 W1 => bool2Word(W0 #push ... [trusted] 9 | rule GT W0 W1 => bool2Word(W0 >Int W1) ~> #push ... [trusted] 10 | rule EQ W0 W1 => bool2Word(W0 ==Int W1) ~> #push ... [trusted] 11 | rule ISZERO W => bool2Word(W ==Int 0 ) ~> #push ... [trusted] 12 | 13 | endmodule 14 | -------------------------------------------------------------------------------- /resources/abstract-semantics-segmented-gas.k: -------------------------------------------------------------------------------- 1 | requires "evm-symbolic.k" 2 | 3 | module ABSTRACT-SEMANTICS-SEGMENTED-GAS 4 | imports EVM 5 | imports EVM-SYMBOLIC 6 | 7 | // to avoid unnecessary case analyses 8 | rule LT W0 W1 => bool2Word(W0 #push ... [trusted] 9 | rule GT W0 W1 => bool2Word(W0 >Int W1) ~> #push ... [trusted] 10 | rule EQ W0 W1 => bool2Word(W0 ==Int W1) ~> #push ... [trusted] 11 | rule ISZERO W => bool2Word(W ==Int 0 ) ~> #push ... [trusted] 12 | 13 | // ######################## 14 | // Segmented gas representatioon - #gas construct 15 | // ######################## 16 | 17 | // accumulate the gas cost and never run out of gas 18 | rule MEM' ~> #deductMemoryGas => . ... 19 | #gas(INITGAS, NONMEM, MEM) => #gas(INITGAS, NONMEM, MEM +Int MEM') 20 | _ => #gas(INITGAS, NONMEM, MEM) 21 | [trusted, matching(#gas)] 22 | 23 | //Will run only if rule above doesn't match 24 | rule G ~> #deductGas => . ... 25 | #gas(INITGAS, NONMEM, MEM) => #gas(INITGAS, NONMEM +Int G, MEM) 26 | _ => #gas(INITGAS, NONMEM, MEM) 27 | [trusted, matching(#gas)] 28 | 29 | endmodule 30 | -------------------------------------------------------------------------------- /resources/build-html.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | for doc in $(find . -name '*.md' \! -name 'sum-to-n.md') ; do 3 | pandoc --lua-filter=resources/relink.lua -so ${doc%.md}.html $doc 4 | done 5 | # build files that have TeX equations 6 | for doc in resources/sum-to-n.md ; do 7 | pandoc --lua-filter=resources/relink.lua --mathjax=https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-MML-AM_CHTML -so ${doc%.md}.html $doc 8 | done 9 | -------------------------------------------------------------------------------- /resources/debugging.md: -------------------------------------------------------------------------------- 1 | # EVM Verifier Debugging Cheatsheet 2 | 3 | 4 | ### Internal commands for running kprover 5 | 6 | ``` 7 | $ cd evm-semantics 8 | $ make deps defn split-proof-tests 9 | $ export PATH=`pwd`/.build/k/k-distribution/target/release/k/bin:$PATH 10 | $ kompile --debug --backend java -I .build/defn/java -d .build/defn/java --main-module ETHEREUM-SIMULATION --syntax-module ETHEREUM-SIMULATION .build/defn/java/driver.k 11 | $ kprove tests/proofs/specs/vyper-erc20/totalSupply-spec.k -d .build/defn/java -m VERIFICATION --z3-executable 12 | ``` 13 | 14 | 15 | ### IntelliJ debugger setup 16 | 17 | 1. Install Intellij (remember to install scala plugin) 18 | 1. In the `k5` dir, `mvn package` 19 | 1. Import k5 project: 20 | 1. Import Project -> Path to the pom.xml 21 | 2. Select project SDK: JDK1.8 22 | 1. Edit Configuration 23 | 1. Click Edit Configuration, click `+` and choose Application 24 | 2. Enter 25 | * Main class: `org.kframework.main.Main` 26 | * VM options: `-Xms64m -Xmx4g -Xss32m -XX:+TieredCompilation -ea` 27 | * Program arguments: `-kprove /path/to/spec.k -d .build/defn/java -m VERIFICATION ` see [kprove tutorial](https://github.com/runtimeverification/verified-smart-contracts/blob/master/resources/kprove-tutorial.md) 28 | * Working dir: `/path/to/evm-semantics` 29 | * Env Variables: 30 | * `LD_LIBRARY_PATH` : `$LD_LIBRARY_PATH:$MODULE_DIR$/../k-distribution/target/release/k/lib/native/linux64` 31 | * `PATH` : `$PATH:$MODULE_DIR$/../k-distribution/target/release/k/bin:$MODULE_DIR$/../k-distribution/target/release/k/lib/native/linux:$MODULE_DIR$/../k-distribution/target/release/k/lib/native/linux64:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin` 32 | * Use classpath of module: `k-distribution` 33 | 34 | 1. Breakpoints 35 | * Start from `proveRule()` in `SymbolicRewriter.java`. 36 | * At line `if (term.implies(targetTerm)) {`. 37 | Set a breakpoint with the following condition, which will stop at the begining of the execution of each opcode. 38 | ``` 39 | ((KList) ((KItem) ((KList) ((KItem) term.term()).kList()).get(0)).kList()).get(0).toString().startsWith("#KSequence(#exec[_]") 40 | ``` 41 | You can also add `step >= N` to constrain the number of steps. 42 | * More recent versions of K have updated versions of the method `proveRule()`. You can move the breakpoint to one of the first lines of `for (ConstrainedTerm term : queue)`, such as `v++`, and use the same condition as above. 43 | 2. Using the debugger 44 | * The debugger should stop at each opcode. You can see the current opcode at the top of the `` cell of the current configuration. The current configuration is stored in the `term` variable. 45 | 46 | ### FAQ 47 | **Q:** The following error was thrown while I was trying to run the debugger. What should I do? 48 | ``` 49 | java.lang.OutOfMemoryError: GC overhead limit exceeded 50 | ``` 51 | **A:** This error was thrown most likely because the memory heap size of the VM was not big enough. In order to fix this error try to increase the heap size by editing the current configuration and replace in the `VM Options` the `-Xmx4g` with `-Xmx12g`. This will allocate 12GB for the VM memory heap. -------------------------------------------------------------------------------- /resources/ecrec-symbolic.k: -------------------------------------------------------------------------------- 1 | requires "edsl.k" 2 | requires "evm-symbolic.k" 3 | 4 | module ECREC-SYMBOLIC [symbolic] 5 | imports K-REFLECTION 6 | imports EVM 7 | imports EDSL 8 | imports EVM-SYMBOLIC 9 | 10 | // ######################## 11 | // ECRECOVER 12 | // ######################## 13 | 14 | rule ECREC => #end EVMC_SUCCESS ... 15 | DATA 16 | _ => #ecrec(#symEcrec(DATA)) 17 | requires notBool #isConcrete(DATA) andBool #sizeWordStack(DATA) ==Int 128 andBool notBool #ecrecEmpty(DATA) 18 | [trusted] 19 | 20 | rule ECREC => #end EVMC_SUCCESS ... 21 | DATA 22 | _ => #ecrec(.Account) 23 | requires notBool #isConcrete(DATA) andBool #sizeWordStack(DATA) ==Int 128 andBool #ecrecEmpty(DATA) 24 | [trusted] 25 | 26 | endmodule 27 | -------------------------------------------------------------------------------- /resources/edsl.md: -------------------------------------------------------------------------------- 1 | eDSL: Domain-Specific Language for EVM Specifications 2 | ===================================================== 3 | 4 | The [K-framework] provides a [reachability logic theorem prover] that is parameterized by the langauge semantics. 5 | Instantiated with the [KEVM], a complete formal semantics of the Ethereum Virtual Machine (EVM), 6 | the K prover yields a correct-by-construction deductive program verifer for the EVM. 7 | The EVM verifier takes an EVM bytecode and a specification as inputs, and automatically proves that the bytecode satisfies the specification, if it is the case. 8 | The EVM specification essentially specifies the pre- and post-conditions of the EVM bytecode in the form of reachability logic claims. 9 | 10 | We present a domain-specific language (DSL) for the EVM specifications, called eDSL, to succintly specify the specifications. 11 | The eDSL consists of two parts: 12 | 13 | * [eDSL High-Level Notations](https://github.com/kframework/evm-semantics/blob/master/edsl.md) 14 | * [eDSL Specifications](edsl-spec.md) 15 | * [eDSL Specification Templates](edsl-spec.md#edsl-specification-template) 16 | * [eDSL Template Parameters](edsl-spec.md#edsl-template-parameters) 17 | 18 | [KEVM]: 19 | [K-framework]: 20 | [reachability logic theorem prover]: 21 | -------------------------------------------------------------------------------- /resources/evm-data-map-concrete.k: -------------------------------------------------------------------------------- 1 | requires "edsl.k" 2 | 3 | module EVM-DATA-MAP-CONCRETE [symbolic] 4 | imports K-REFLECTION 5 | imports EVM-DATA 6 | imports EDSL 7 | 8 | // Same rules exist in KEVM, but are marked [concrete]. Allowing them for symbolic arguments here. 9 | 10 | rule #lookup( (KEY |-> VAL) M, KEY ) => VAL 11 | rule #lookup( M, KEY ) => 0 requires notBool KEY in_keys(M) 12 | 13 | rule #range(WM, START, WIDTH) => #range(WM, START +Int WIDTH -Int 1, WIDTH, .WordStack) 14 | 15 | rule WM[ N := W : WS ] => (WM[N <- W])[N +Int 1 := WS] 16 | 17 | //semantics of #buf 18 | rule #buf(LEN, BYTES) => #padToWidth(LEN, #asByteStack( BYTES )) 19 | 20 | endmodule 21 | -------------------------------------------------------------------------------- /resources/evm-direct-gas.k: -------------------------------------------------------------------------------- 1 | requires "edsl.k" 2 | 3 | module EVM-DIRECT-GAS [symbolic] 4 | imports EVM 5 | imports EDSL 6 | 7 | // ######################## 8 | // Direct gas representatioon as number - rules copy-pasted from KEVM but without [concrete] 9 | // ######################## 10 | 11 | // Rules from evm.md that got [concrete] as part of migration to segmented gas model. 12 | // Only enabling the subset that is needed for current specs. 13 | //----------------------------------------- 14 | 15 | /* 16 | rule #memoryUsageUpdate(MU, START, WIDTH) => maxInt(MU, (START +Int WIDTH) up/Int 32) requires WIDTH >Int 0 17 | 18 | rule Cgascap(SCHED, GCAP, GAVAIL, GEXTRA) 19 | => #if GAVAIL > #then GCAP #else minInt(#allBut64th(GAVAIL -Int GEXTRA), GCAP) #fi 20 | */ 21 | rule Csstore(SCHED, NEW, CURR, ORIG) 22 | => #if CURR ==Int NEW orBool ORIG =/=Int CURR #then Gsload < SCHED > #else #if ORIG ==Int 0 #then Gsstoreset < SCHED > #else Gsstorereset < SCHED > #fi #fi 23 | requires Ghasdirtysstore << SCHED >> 24 | 25 | rule Csstore(SCHED, NEW, CURR, ORIG) 26 | => #if CURR ==Int 0 andBool NEW =/=Int 0 #then Gsstoreset < SCHED > #else Gsstorereset < SCHED > #fi 27 | requires notBool Ghasdirtysstore << SCHED >> 28 | 29 | rule Rsstore(SCHED, NEW, CURR, ORIG) 30 | => #if CURR =/=Int NEW andBool ORIG ==Int CURR andBool NEW ==Int 0 #then 31 | Rsstoreclear < SCHED > 32 | #else 33 | #if CURR =/=Int NEW andBool ORIG =/=Int CURR andBool ORIG =/=Int 0 #then 34 | #if CURR ==Int 0 #then 0 -Int Rsstoreclear < SCHED > #else #if NEW ==Int 0 #then Rsstoreclear < SCHED > #else 0 #fi #fi 35 | #else 36 | 0 37 | #fi +Int 38 | #if CURR =/=Int NEW andBool ORIG ==Int NEW #then 39 | #if ORIG ==Int 0 #then Gsstoreset < SCHED > #else Gsstorereset < SCHED > #fi -Int Gsload < SCHED > 40 | #else 41 | 0 42 | #fi 43 | #fi 44 | requires Ghasdirtysstore << SCHED >> 45 | 46 | rule Rsstore(SCHED, NEW, CURR, ORIG) 47 | => #if CURR =/=Int 0 andBool NEW ==Int 0 #then Rsstoreclear < SCHED > #else 0 #fi 48 | requires notBool Ghasdirtysstore << SCHED >> 49 | 50 | /* 51 | rule Cextra(SCHED, ISEMPTY, VALUE) 52 | => Gcall < SCHED > +Int Cnew(SCHED, ISEMPTY, VALUE) +Int Cxfer(SCHED, VALUE) 53 | 54 | rule Cmem(SCHED, N) => (N *Int Gmemory < SCHED >) +Int ((N *Int N) /Int Gquadcoeff < SCHED >) 55 | */ 56 | 57 | endmodule 58 | -------------------------------------------------------------------------------- /resources/evm-symbolic.k: -------------------------------------------------------------------------------- 1 | requires "edsl.k" 2 | 3 | module EVM-SYMBOLIC [symbolic] 4 | imports EVM 5 | imports EDSL 6 | 7 | // ######################## 8 | // Ecrecover 9 | // todo move to ecrec-symbolic.k when K supports it. 10 | // ######################## 11 | 12 | //Symbolic wrapper over the argument of #ecrec, no implementation. 13 | syntax Int ::= #symEcrec ( WordStack ) [function] 14 | 15 | //Symbolic predicate representing whether output of #ecrec is empty. No implementation. 16 | syntax Bool ::= #ecrecEmpty( WordStack ) [function] 17 | 18 | // Range for #symEcrec 19 | 20 | //case 0 is never wrapped into #symEcrec(), corresponds to #ecrecEmpty(DATA) == true 21 | rule 0 true 22 | 23 | //that's because the result in concrete semantics is trimmed to Address range. 24 | rule #symEcrec(DATA) true 25 | 26 | // Lemmas implied by the above, but still required to match side conditions of #padToWidth rule in lemmas.md 27 | // General range conversion lemmas like below are not an option, dramatic performance decrease: 28 | // rule A < pow256 => true requires A < pow160 29 | rule 0 <=Int #symEcrec(DATA) => true 30 | rule #symEcrec(DATA) true 31 | 32 | // ######################## 33 | // Symbolic Gas 34 | // ######################## 35 | 36 | syntax Int ::= #gas ( Int , Int , Int ) [function] // startGas, nonMemory, memory 37 | // ----------------------------------------------------------------------------------- 38 | /* 39 | startGas - gas available at the beginning of execution 40 | nonMemory - gas consumed on non-memory operations 41 | memory - gas consumed on memory operation 42 | 43 | Concrete semantics: 44 | 45 | rule #gas ( StartGas , NonMemory , Memory ) => StartGas -Int NonMemory -Int Memory 46 | */ 47 | 48 | syntax Int ::= #symCmem ( Int ) [function] 49 | // ------------------------------------------- 50 | 51 | // callSuccess? caputures various cases where a call may fail including out of gas, insufficient balance and etc. 52 | // TODO: include the calldata as the argument. 53 | syntax Int ::= #callGas ( Schedule , Int , Int , Int , Bool ) [function] // schedule, gasCap, accountTo, value, callSuccess? 54 | // ------------------------------------------------------------------------------------------------------------------------------ 55 | 56 | 57 | // ######################## 58 | // Symbolic Call 59 | // ######################## 60 | 61 | // PC helps to differentiate different calls to the same account. 62 | // TODO: include the calldata as the argument. 63 | syntax Bool ::= #callSuccess ( Int , Int ) [function] // pc, accountTo 64 | | #callFailure ( Int , Int ) [function] // pc, accountTo 65 | // ------------------------------------------------------------------------ 66 | 67 | syntax Int ::= #callResult ( Int , Int ) [function] // pc, accountTo 68 | // ---------------------------------------------------------------------- 69 | 70 | 71 | syntax Int ::= #extCodeSize ( Int ) [function] 72 | // ----------------------------------------------- 73 | 74 | // ERC20 transfer(address,uint256) 75 | // pc, to addr 76 | syntax Bool ::= #tokenTransferCallSuccess ( Int , Int ) [function] 77 | | #tokenTransferCallFailure ( Int , Int ) [function] 78 | // ------------------------------------------------------------------ 79 | 80 | // 3rd argument: NOW variable hack to force to generate Z3 query 81 | syntax Int ::= #tokenTransferCallReturnSize ( Int , Int , Int ) [function] 82 | | #tokenTransferCallReturnValue ( Int , Int , Int ) [function] 83 | // --------------------------------------------------------------------------- 84 | 85 | endmodule 86 | -------------------------------------------------------------------------------- /resources/evm.smt2: -------------------------------------------------------------------------------- 1 | ; (set-option :auto-config false) 2 | ; (set-option :smt.mbqi false) 3 | ; (set-option :smt.array.extensional false) 4 | 5 | ; int extra 6 | (define-fun int_max ((x Int) (y Int)) Int (ite (< x y) y x)) 7 | (define-fun int_min ((x Int) (y Int)) Int (ite (< x y) x y)) 8 | (define-fun int_abs ((x Int)) Int (ite (< x 0) (- 0 x) x)) 9 | 10 | ; bool to int 11 | (define-fun smt_bool2int ((b Bool)) Int (ite b 1 0)) 12 | 13 | ; ceil32 14 | (define-fun ceil32 ((x Int)) Int ( * ( div ( + x 31 ) 32 ) 32 ) ) 15 | -------------------------------------------------------------------------------- /resources/gen-spec.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | import configparser 6 | 7 | def app(specs, spec): 8 | if not specs: 9 | return spec 10 | else: 11 | delimiter = "\n\n" 12 | return delimiter.join((specs, spec)) 13 | 14 | # TODO: for Python 3.5 or higher: z = {**x, **y} 15 | def merge_two_dicts(x, y): 16 | z = dict(x) 17 | z.update(y) 18 | return z 19 | 20 | def subst(text, key, val): 21 | return text.replace('{' + key.upper() + '}', val) 22 | 23 | def safe_get(config, section): 24 | if section in config: 25 | return config[section] 26 | else: 27 | return {} 28 | 29 | def inherit_get(config, section): 30 | if not section: 31 | return safe_get(config, 'root') 32 | else: 33 | parent = inherit_get(config, '-'.join(section.split('-')[:-1])) 34 | current = safe_get(config, section) 35 | merged = merge_two_dicts(parent, current) # TODO: for Python 3.5 or higher: {**parent, **current} 36 | for key in list(merged.keys()): 37 | if key.startswith('+'): 38 | merged[key[1:]] += merged[key] 39 | del merged[key] 40 | return merged 41 | 42 | def gen(spec_template, rule_template, spec_ini, spec_name, rule_name_list): 43 | spec_config = configparser.ConfigParser(comment_prefixes=(';')) 44 | spec_config.read(spec_ini) 45 | if 'pgm' not in spec_config: 46 | print('''Must specify a "pgm" section in the .ini file.''') 47 | sys.exit(1) 48 | pgm_config = spec_config['pgm'] 49 | rule_spec_list = [] 50 | for name in rule_name_list: 51 | rule_spec = rule_template 52 | for config in [ inherit_get(spec_config, name) 53 | , pgm_config 54 | ]: 55 | rule_spec = subst_all(rule_spec, config) 56 | # for key in config: 57 | # rule_spec = subst(rule_spec, key, config[key].strip()) 58 | rule_spec = subst(rule_spec, "rulename", name) 59 | rule_spec_list.append(rule_spec) 60 | delimeter = "\n" 61 | rules = delimeter.join(rule_spec_list) 62 | genspec = subst(spec_template, 'module', spec_name.upper()) 63 | genspec = subst(genspec, 'rules', rules) 64 | print(genspec) 65 | # genspec = template 66 | # for config in [ inherit_get(spec_config, name) 67 | # , {'module': name.upper()} 68 | # , pgm_config['DEFAULT'] 69 | # ]: 70 | # for key in config: 71 | # genspec = subst(genspec, key, config[key].strip()) 72 | # print(genspec) 73 | 74 | def subst_all(init_rule_spec, config): 75 | rule_spec = init_rule_spec 76 | for key in config: 77 | rule_spec = subst(rule_spec, key, config[key].strip()) 78 | if rule_spec != init_rule_spec: 79 | return subst_all(rule_spec, config) 80 | else: 81 | return rule_spec 82 | 83 | if __name__ == '__main__': 84 | if len(sys.argv) < 6: 85 | print("usage: ") 86 | sys.exit(1) 87 | spec_template = open(sys.argv[1], "r").read() 88 | rule_template = open(sys.argv[2], "r").read() 89 | gen(spec_template, rule_template, sys.argv[3], sys.argv[4], sys.argv[5:]) 90 | -------------------------------------------------------------------------------- /resources/instructions.md: -------------------------------------------------------------------------------- 1 | # General Instruction for Reproducing Mechanized Proofs 2 | 3 | The formal specifications presented in this repository are written in [eDSL], a domain-specific language for EVM specifications, which must be known in order to thoroughly understand the specifications. 4 | Refer to [resources] for background on our technology. 5 | Each of the specifications provides the [eDSL] specification template parameters. 6 | The full [K] [reachability logic] specifications are automatically derived by instantiating a specification template with these template parameters. 7 | 8 | #### Generating Full Reachability Logic Specifications 9 | 10 | Run the following command in the root directory of this repository, and it will generate the full [reachability logic] specifications, under the directory `specs`, for the smart contract(s) in the `` directory: 11 | 12 | ``` 13 | $ make -C split-proof-tests 14 | ``` 15 | 16 | #### Reproducing Proofs 17 | 18 | To prove that the specifications are satisfied by (the compiled EVM bytecode of) the target contracts, run the EVM verifier as follows: 19 | 20 | ``` 21 | $ make -C test 22 | ``` 23 | 24 | #### Installing the EVM Verifier 25 | 26 | The EVM verifier is part of the [KEVM] project. The following commands will successfully install it, provided that all of the dependencies are installed. 27 | 28 | ``` 29 | $ make -C deps 30 | ``` 31 | 32 | For detailed instructions on installing and running the EVM verifier, see [KEVM]'s [Installing/Building](https://github.com/kframework/evm-semantics/blob/master/README.md#installingbuilding) and [Example Usage](https://github.com/kframework/evm-semantics/blob/master/README.md#example-usage) pages. 33 | 34 | ## [Resources](/README.md#resources) 35 | 36 | ## [Disclaimer](/README.md#disclaimer) 37 | 38 | [K]: 39 | [eDSL]: 40 | [KEVM]: 41 | [reachability logic]: 42 | [resources]: 43 | -------------------------------------------------------------------------------- /resources/kprove-group.mak: -------------------------------------------------------------------------------- 1 | SUBCLEAN=$(addsuffix .clean,$(SUBDIRS)) 2 | SUBCLEANDEPS=$(addsuffix .clean-deps,$(SUBDIRS)) 3 | SUBDEPS=$(addsuffix .deps,$(SUBDIRS)) 4 | SUBPROOF=$(addsuffix .proof,$(SUBDIRS)) 5 | SUBTEST=$(addsuffix .test,$(SUBDIRS)) 6 | 7 | .PHONY: all clean clean-deps deps split-proof-tests test $(SUBDIRS) $(SUBCLEAN) $(SUBCLEANDEPS) $(SUBDEPS) $(SUBPROOF) $(SUBTEST) 8 | 9 | all: $(SUBDIRS) 10 | clean: $(SUBCLEAN) 11 | clean-deps: $(SUBCLEANDEPS) 12 | deps: $(SUBDEPS) 13 | split-proof-tests: $(SUBPROOF) 14 | test: $(SUBTEST) 15 | 16 | $(SUBDIRS): 17 | $(MAKE) -C $@ 18 | 19 | $(SUBCLEAN): %.clean: 20 | $(MAKE) -C $* clean 21 | 22 | $(SUBCLEANDEPS): %.clean-deps: 23 | $(MAKE) -C $* clean-deps 24 | 25 | $(SUBDEPS): %.deps: 26 | $(MAKE) -C $* deps 27 | 28 | $(SUBPROOF): %.proof: 29 | $(MAKE) -C $* split-proof-tests 30 | 31 | $(SUBTEST): %.test: 32 | $(MAKE) -C $* test 33 | 34 | # 35 | # For Jenkins Build 36 | # 37 | 38 | NPROCS?=1 39 | 40 | .PHONY: jenkins 41 | 42 | # K bug workaround: Because KEVM parse cache is shared between projects, rules with equal body but different attributes will collide. 43 | # That's why we need clean-kevm-cache below. 44 | jenkins: 45 | set -e; \ 46 | for i in $(SUBDIRS); do \ 47 | $(MAKE) -C $$i clean-kevm-cache all; \ 48 | $(MAKE) -C $$i test -j$(NPROCS); \ 49 | done 50 | -------------------------------------------------------------------------------- /resources/not-KLabel.k: -------------------------------------------------------------------------------- 1 | module NOT-KLABEL [symbolic] 2 | imports K-REFLECTION 3 | 4 | //Returns true if the KLabel of `T` is not `L`, or if `T` is a variable. 5 | syntax Bool ::= #notKLabel ( K , String ) [function] 6 | rule #notKLabel(T, L) => #getKLabelString(T) =/=String L orBool #isVariable(T) 7 | 8 | endmodule 9 | -------------------------------------------------------------------------------- /resources/pdf-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/verified-smart-contracts/e61ef57de99d07d7182436490f152a14621c5a82/resources/pdf-icon.png -------------------------------------------------------------------------------- /resources/relink.lua: -------------------------------------------------------------------------------- 1 | function fix_local_links(link) 2 | if not string.find("://",link.target) then 3 | link.target = string.gsub(link.target,"%.md$",".html") 4 | link.target = string.gsub(link.target,"%.md#(.*)$",".html#%1") 5 | end 6 | return link 7 | end 8 | 9 | local first_header = true 10 | local my_title = nil 11 | 12 | function find_title(header) 13 | if first_header == true then 14 | if header.level == 1 then 15 | my_title = header.content 16 | end 17 | first_header = false 18 | end 19 | return header 20 | end 21 | 22 | function do_metadata(m) 23 | if m['title'] == nil and m['pagetitle'] == nil then 24 | m['pagetitle'] = my_title 25 | end 26 | return m 27 | end 28 | 29 | return {{Link = fix_local_links, Header = find_title}, 30 | {Meta = do_metadata}} 31 | -------------------------------------------------------------------------------- /run-proofs.sh: -------------------------------------------------------------------------------- 1 | # Usage in evm-semantics/tests/proofs: 2 | # E.g. ./run-proofs gnosis-erc20 gnosis-erc20-1 3 | # $1: folder in ./specs 4 | # $2: output folder 5 | # $3...: files to be verified 6 | # OR 7 | # $3: all/empty = all 8 | 9 | options=( \ 10 | # '--log-basic' \ 11 | # '--log-cells "(k),(gas),(statusCode)"' \ 12 | # '--log --log-cells "(k),(pc),(wordStack)"' \ 13 | # '--log-cells "(k),(output),(localMem),(pc),(gas),(wordStack),(accounts)"' \ 14 | ) 15 | 16 | output_top_dir="output" 17 | output_dir="$2" 18 | 19 | mkdir -p "$output_top_dir/$output_dir" 20 | touch "$output_top_dir/$output_dir/log" 21 | 22 | # Assuming an (exported) KEVM environmental variable. 23 | # If you don't have one, uncomment this and set it here: 24 | 25 | # KEVM="/Users" 26 | 27 | run_proof() { 28 | touch "$output_top_dir/$output_dir/$file_name" 29 | 30 | cmd_part1="kprove "$file_path" -d "${KEVM}/.build/defn/java" -m VERIFICATION" 31 | cmd_part2="&> "$output_top_dir/$output_dir/$file_name"" 32 | cmd="$cmd_part1 ${options[@]} $cmd_part2" 33 | 34 | log="$(date): Verifying $file_name with ${options[@]}" 35 | echo "$log" >> "$output_top_dir/$output_dir/log" 36 | echo "$log" 37 | 38 | eval "$cmd" 39 | } 40 | 41 | if [ "$3" == "all" ] || [ -z "$3" ] 42 | then 43 | for file in ./specs/"$1"/* 44 | do 45 | file_name="${file##*/}" 46 | file_end="${file:(-6)}" 47 | if [ "$file_end" == "spec.k" ] 48 | then 49 | file_path="${file:2}" 50 | run_proof "$@" 51 | else 52 | echo "skipping $file_name because it is not a spec file" 53 | fi 54 | done 55 | else 56 | i=3 57 | if [ "$3" == "-d" ] 58 | then 59 | echo "deleting $output_top_dir/$output_dir" 60 | rm -rf "$output_top_dir/$output_dir/*" 61 | i=4 62 | fi 63 | for ((j=i; j <= $#; j++ )); do 64 | file_name="${!j}" 65 | file_path="specs/$1/$file_name" 66 | if [ -e "$file_path" ] 67 | then 68 | run_proof "$@" 69 | else 70 | echo "skipping $file_name because it does not exist - maybe a typo?" 71 | fi 72 | done 73 | fi -------------------------------------------------------------------------------- /script/dkprove.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | kprove --debugg \ 4 | --output-omit "" --output-omit "" --output-omit "" \ 5 | --output-omit "" --output-omit "" --output-omit "" --output-omit "" \ 6 | --output-omit "" --output-omit "" --output-omit "" --output-omit "" \ 7 | --output-omit "" --output-omit "" --output-omit "" --output-omit "" \ 8 | --output-omit "" --output-omit "" --output-omit "" --output-omit "" \ 9 | --output-omit "" --output-omit "" --output-omit "" --output-omit "" \ 10 | --output-omit "" --output-omit "" --output-omit "" --output-omit "" \ 11 | --output-omit "" --output-omit "" --output-omit "" --output-omit "" \ 12 | --output-omit "" --output-omit "" --output-omit "" --output-omit "" \ 13 | --output-omit "" --output-omit "" --output-omit "" --output-omit "" \ 14 | --output-omit "" --output-omit "" --output-omit "" \ 15 | --output-tostring "" \ 16 | --output-tokenize "" --output-tostring "" --output-tostring "" --output-tostring "" \ 17 | --output-tostring "" --output-tostring "" --output-tostring "" --output-tostring "" \ 18 | --output-tostring "" --output-tokenize "#And" --output-tokenize "_==K_" --output-flatten "_|->_" \ 19 | "$@" 20 | -------------------------------------------------------------------------------- /script/kprove_log.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.6 2 | import re 3 | import sys 4 | import json 5 | import types 6 | import os 7 | 8 | from typing import List 9 | 10 | 11 | def main(debuggDir): 12 | debugg_lines = [line.rstrip('\n') for line in open(debuggDir + "/debugg.log", "r")] 13 | branch_logged = False 14 | for line in debugg_lines: 15 | if " node " in line: 16 | process_node(line) 17 | branch_logged = False 18 | elif " branch " in line and not branch_logged: 19 | print("\nBranching!\n======================================================\n") 20 | branch_logged = True 21 | 22 | 23 | # 93384 node 12_1_487122957_80037969 12_1_487122957_80037969 24 | # time "node" step_pathId_term_constraint 25 | rstep_pattern = re.compile("(\d+) node (\d+)_(\d+)_(\d+)_(\d+)") 26 | 27 | 28 | def process_node(line): 29 | (time, step, pathId, termId, constrId) = rstep_pattern.match(line).groups() 30 | with open("{}/nodes/{}.json".format(debuggDir, termId), "r") as f: 31 | term = json.load(f) 32 | with open("{}/nodes/{}.json".format(debuggDir, constrId), "r") as f: 33 | constraint = json.load(f) 34 | 35 | print("\nSTEP {} path {} in {} ms\n======================================================\n" 36 | .format(step, pathId, time)) 37 | printTerm(term["term"], None) 38 | 39 | print("/\\") 40 | printTerm(constraint["term"], None) 41 | 42 | 43 | def printTerm(term, label, end='\n'): 44 | nodeType = term["node"] 45 | if nodeType == "KApply": 46 | if term["label"] == "#And": 47 | printTerm(term["args"][0], None, end="") 48 | print(" #And") 49 | printTerm(term["args"][1], None) 50 | else: 51 | cells = term["args"] 52 | for cell in cells: 53 | printTerm(cell, term["label"]) 54 | else: 55 | cellOut = term["token"] if nodeType == "KToken" \ 56 | else term["name"] if nodeType == "KVariable" \ 57 | else term["name"] if nodeType == "KVariable" \ 58 | else term 59 | print((label + ": " if label is not None else "") + cellOut, end=end) 60 | 61 | 62 | if __name__ == '__main__': 63 | if len(sys.argv) != 2: 64 | print("One argument expected: debugg dir") 65 | sys.exit(1) 66 | debuggDir = sys.argv[1] 67 | main(debuggDir) 68 | -------------------------------------------------------------------------------- /uniswap/.build/.kevm.rev: -------------------------------------------------------------------------------- 1 | 06b124d984d239268f37595db6ebcf6aee656a31 2 | -------------------------------------------------------------------------------- /uniswap/Makefile: -------------------------------------------------------------------------------- 1 | # Hack to have specs/uniswap/lemmas.k separate from specs/lemmas.k 2 | SPEC_GROUP:=uniswap/uniswap 3 | 4 | KEVM_VERSION_FILE:=.build/.kevm.rev 5 | 6 | BASEDIR_LEMMAS:=lemmas.md 7 | LOCAL_LEMMAS:=abstract-semantics.k verification.k 8 | TMPLS:=module-tmpl.k spec-tmpl.k 9 | 10 | SPEC_NAMES:=addLiquidity-1 \ 11 | addLiquidity-2 \ 12 | removeLiquidity \ 13 | ethToTokenSwapInput \ 14 | ethToTokenSwapOutput 15 | 16 | override KEVM_BUILD_DIR=$(KEVM_REPO_DIR)/.build/$(K_BACKEND) 17 | 18 | include ../resources/kprove.mak 19 | -------------------------------------------------------------------------------- /uniswap/abstract-semantics.k: -------------------------------------------------------------------------------- 1 | module ABSTRACT-SEMANTICS 2 | imports EVM 3 | 4 | // to avoid unnecessary case analyses 5 | rule LT W0 W1 => bool2Word(W0 #push ... [trusted] 6 | rule GT W0 W1 => bool2Word(W0 >Int W1) ~> #push ... [trusted] 7 | rule EQ W0 W1 => bool2Word(W0 ==Int W1) ~> #push ... [trusted] 8 | rule ISZERO W => bool2Word(W ==Int 0 ) ~> #push ... [trusted] 9 | 10 | endmodule 11 | -------------------------------------------------------------------------------- /uniswap/issues.md: -------------------------------------------------------------------------------- 1 | We list all the issues we found in the inital version ([commit fddd25e](https://github.com/Uniswap/contracts-vyper/blob/fddd25e9ab5602535bb00e3f5d44296e08d9a0fc/contracts/uniswap_exchange.vy)) and subsequent commits. 2 | 3 | ## Rounding errors 4 | 5 | We found several rounding error issues in the code. 6 | 7 | * In `addLiquidity` function, `token_amount` computed on [line 51](https://github.com/Uniswap/contracts-vyper/blob/fddd25e9ab5602535bb00e3f5d44296e08d9a0fc/contracts/uniswap_exchange.vy#L51) is less than the actual value. The issue was fixed in [commit 2c29ee8](https://github.com/Uniswap/contracts-vyper/commit/2c29ee8943bc12a4f3cfaad58c2092396aa579c1) 8 | 9 | * In `ethToToken`([line 92](https://github.com/Uniswap/contracts-vyper/blob/fddd25e9ab5602535bb00e3f5d44296e08d9a0fc/contracts/uniswap_exchange.vy#L92)) and `ethToTokenExact`([line 110](https://github.com/Uniswap/contracts-vyper/blob/fddd25e9ab5602535bb00e3f5d44296e08d9a0fc/contracts/uniswap_exchange.vy#L110)) functions, the way to compute final results uses two integer divisions, and thus the error cannot be bounded. We proposed a better way to compute the results and reduced the error to at most 1. The issue was fixed in [commit 7b23a2e](https://github.com/Uniswap/contracts-vyper/commit/7b23a2e60a1c8ff5d4b88fd4f83e74467256f8da). 10 | 11 | ## Other implementation issues 12 | 13 | * On [line 28](https://github.com/Uniswap/contracts-vyper/blob/fddd25e9ab5602535bb00e3f5d44296e08d9a0fc/contracts/uniswap_exchange.vy#L28), return value of `setup` function is not necessary. The issue was fixed in [commit (3cdbb98)](https://github.com/Uniswap/contracts-vyper/commit/3cdbb9881331a494c090edf5e7920a39b2fbec8f). 14 | 15 | * In `getEthToToken`([line 104](https://github.com/Uniswap/contracts-vyper/blob/fddd25e9ab5602535bb00e3f5d44296e08d9a0fc/contracts/uniswap_exchange.vy#L104)) and `getTokenToEth`([line 120](https://github.com/Uniswap/contracts-vyper/blob/fddd25e9ab5602535bb00e3f5d44296e08d9a0fc/contracts/uniswap_exchange.vy#L120)) functions, since no call value is passed to the two functions, `self.balance` is not modified. As a result, they should not directly call `ethToToken` and `ethToTokenExact` functions. The issue was fixed in [commit 0612ebf](https://github.com/Uniswap/contracts-vyper/commit/0612ebf7621b886f7178fafd9a8ac41026a37296) and was further fixed in [commit 2c29ee8](https://github.com/Uniswap/contracts-vyper/commit/7b23a2e60a1c8ff5d4b88fd4f83e74467256f8da). 16 | 17 | * Several uncessary assertions were removed in [commit ae2aec9](https://github.com/Uniswap/contracts-vyper/commit/ae2aec9a6128c6f28e7acfa793b9a647822179b8). 18 | 19 | * We noticed that when comparing the computed value with user defined min/max value, `<` and `>` were used instead of `<=` and `>=`. The issue was fixed in [commit fa912634](https://github.com/Uniswap/contracts-vyper/commit/fa91263460d3f4fc5482c2d9e9c89d93fe43708f). 20 | 21 | * In `tokenToTokenExact`function([line 269](https://github.com/Uniswap/contracts-vyper/blob/d4cfffd2eb5dda71dbb0a35a23d9f6425bd345a2/contracts/uniswap_exchange.vy#L269)), the developer incorrectly used `min_eth_bought` instead of `max_eth_bought` to bound the ratio from eth to target token. The issue was fixed in [commit 07e86fb](https://github.com/Uniswap/contracts-vyper/commit/07e86fbfad9834ce4288a2704fcd3987c49ab550). 22 | 23 | * We suggested adding `assert msg.value > 0` in the `addLiquidity` function. The issue was fixed in [commit 3956e9a](https://github.com/Uniswap/contracts-vyper/commit/3956e9a493b182ec408cd9d118e2ff4f1ff628ab). 24 | 25 | * We suggested refactoring `ethToToken*/tokenToEther*` functions to extract common code and avoid code duplication. The issue was fixed in [commit 7b23a2e](https://github.com/Uniswap/contracts-vyper/commit/7b23a2e60a1c8ff5d4b88fd4f83e74467256f8da). 26 | 27 | * We found a naming issue on [line 322](https://github.com/Uniswap/contracts-vyper/blob/59418f748ba1465a02f662ed9703892079cf576e/contracts/uniswap_exchange.vy#L322). The issue was fixed in [commit 3956e9a](https://github.com/Uniswap/contracts-vyper/commit/3956e9a493b182ec408cd9d118e2ff4f1ff628ab). 28 | -------------------------------------------------------------------------------- /uniswap/module-tmpl.k: -------------------------------------------------------------------------------- 1 | requires "abstract-semantics.k" 2 | requires "verification.k" 3 | 4 | module {MODULE}-SPEC 5 | imports ABSTRACT-SEMANTICS 6 | imports VERIFICATION 7 | 8 | {RULES} 9 | 10 | endmodule 11 | -------------------------------------------------------------------------------- /uniswap/spec-tmpl.k: -------------------------------------------------------------------------------- 1 | // {RULENAME} 2 | rule 3 | {K} 4 | 1 5 | NORMAL 6 | BYZANTIUM 7 | 8 | 9 | 10 | {OUTPUT} 11 | {STATUSCODE} 12 | _ 13 | _ 14 | _ => _ 15 | 16 | 17 | #asMapOpCodes(#dasmOpCodes(#parseByteStack({CODE}), BYZANTIUM)) 18 | #parseByteStack({CODE}) 19 | 20 | ACCT_ID // contract owner 21 | CALLER_ID // who called this contract; in the begining, origin // msg.sender 22 | {CALLDATA} 23 | {CALLVALUE} 24 | .WordStack => _ 25 | .Map => _ 26 | 0 => _ 27 | _ => _ 28 | 0 => _ 29 | _ => _ 30 | 31 | false // NOTE: non-static call 32 | CALL_DEPTH 33 | 34 | 35 | 36 | _ 37 | {LOG} 38 | {REFUND} // TODO: more detail 39 | 40 | 41 | _ 42 | ORIGIN_ID // who fires tx 43 | 44 | _ 45 | _ 46 | _ 47 | _ 48 | _ 49 | _ 50 | _ 51 | _ 52 | _ 53 | _ 54 | _ 55 | NOW // now = block.timestamp 56 | _ 57 | _ 58 | _ 59 | _ 60 | _ 61 | 62 | 63 | 64 | SetItem(ACCT_ID) _:Set 65 | 66 | 67 | 68 | ACCT_ID 69 | {BALANCE} 70 | #parseByteStack({CODE}) 71 | 72 | {STORAGE} 73 | 74 | _ 75 | 76 | ... 77 | 78 | 79 | _ 80 | _ 81 | _ 82 | 83 | 84 | requires #rangeAddress(ACCT_ID) 85 | andBool #rangeAddress(CALLER_ID) 86 | andBool #rangeAddress(ORIGIN_ID) 87 | andBool #range(0 <= CD < 1024) 88 | andBool #rangeUInt(256, NOW) 89 | andBool ACCT_ID >Int 0 andBool (notBool ACCT_ID in #precompiledAccounts(BYZANTIUM)) 90 | {REQUIRES} 91 | -------------------------------------------------------------------------------- /uniswap/verification.k: -------------------------------------------------------------------------------- 1 | requires "edsl.k" 2 | requires "../lemmas.k" 3 | 4 | module VERIFICATION 5 | imports EDSL 6 | imports LEMMAS 7 | 8 | syntax Int ::= #tokenReserve(Int) [function, smtlib(smt_token_reserve)] 9 | 10 | syntax Int ::= #exchangeAddr(Int) [function, smtlib(smt_exchange_addr)] 11 | 12 | syntax Int ::= #status(Int) [function, smtlib(smt_status)] 13 | 14 | syntax Int ::= #transferFromReturn(Int) [function, smtlib(smt_transfer_from_return)] 15 | 16 | syntax Int ::= #transferReturn(Int) [function, smtlib(smt_transfer_return)] 17 | 18 | 19 | rule EXTCODESIZE ACCTTO => 1 ~> #push ... [trusted] 20 | 21 | // addLiquidity 22 | // #Line 55: self.token.balanceOf(self) 23 | rule STATICCALL GCAP TOKEN_ADDR 1020 36 1120 32 24 | => #status(55) ~> #push ~> #setLocalMem 1120 32 #asByteStackInWidth(#tokenReserve(55), 32) ... [trusted] 25 | 26 | // #Line 61: self.token.transferFrom(msg.sender, self, token_amount) 27 | rule CALL GCAP TOKEN_ADDR 0 1244 100 1408 32 28 | => #status(61) ~> #push ~> #setLocalMem 1408 32 #asByteStackInWidth(#transferFromReturn(61), 32) ... [trusted] 29 | 30 | // #Line 67: self.factory.getExchange(self.token) 31 | rule STATICCALL GCAP FACTORY_ADDR 476 36 576 32 32 | => #status(67) ~> #push ~> #setLocalMem 576 32 #asByteStackInWidth(#exchangeAddr(67), 32) ... [trusted] 33 | 34 | // #Line 72: self.token.transferFrom(msg.sender, self, token_amount) 35 | rule CALL GCAP TOKEN_ADDR 0 700 100 864 32 36 | => #status(72) ~> #push ~> #setLocalMem 864 32 #asByteStackInWidth(#transferFromReturn(72), 32) ... [trusted] 37 | 38 | // removeLiquidity 39 | // #Line 88: self.token.balanceOf(self) 40 | rule STATICCALL GCAP TOKEN_ADDR 540 36 640 32 41 | => #status(88) ~> #push ~> #setLocalMem 640 32 #asByteStackInWidth(#tokenReserve(88), 32) ... [trusted] 42 | 43 | // #Line 94: self.token.transfer(msg.sender, token_amount) 44 | rule CALL GCAP TOKEN_ADDR 0 764 68 896 32 45 | => #status(94) ~> #push ~> #setLocalMem 896 32 #asByteStackInWidth(#transferReturn(94), 32) ... [trusted] 46 | 47 | // send() 48 | rule CALL 0 ACCTTO VALUE 0 0 0 0 => #status(95) ~> #push ... [trusted] 49 | 50 | // ethToTokenSwapInput 51 | // #Line 130: self.token.balanceOf(self) 52 | rule STATICCALL GCAP TOKEN_ADDR 572 36 672 32 53 | => #status(130) ~> #push ~> #setLocalMem 672 32 #asByteStackInWidth(#tokenReserve(130), 32) ... [trusted] 54 | 55 | // #Line 133: self.token.transfer(recipient, tokens_bought) 56 | rule CALL GCAP TOKEN_ADDR 0 988 68 1120 32 57 | => #status(133) ~> #push ~> #setLocalMem 1120 32 #asByteStackInWidth(#transferReturn(133), 32) ... [trusted] 58 | 59 | // ethToTokenSwapOutput 60 | // #Line 170: self.token.balanceOf(self) 61 | // rule STATICCALL GCAP ACCTTO 572 36 672 32 62 | // => 1 ~> #push ~> #setLocalMem 672 32 #asByteStackInWidth(#tokenReserve, 32) ... [trusted] 63 | 64 | // #Line 176: self.token.transfer(recipient, tokens_bought) 65 | rule CALL GCAP ACCTTO 0 1052 68 1184 32 66 | => #status(176) ~> #push ~> #setLocalMem 1184 32 #asByteStackInWidth(#transferReturn(176), 32) ... [trusted] 67 | 68 | // send() 69 | //rule CALL 0 ACCTTO VALUE 0 0 0 0 => 1 ~> #push ... [trusted] 70 | 71 | rule 0 <=Int #tokenReserve(I) => true 72 | 73 | rule #tokenReserve(I) true 74 | 75 | rule 0 <=Int #exchangeAddr(I) => true 76 | 77 | rule #exchangeAddr(I) true 78 | 79 | rule #exchangeAddr(I) true 80 | 81 | rule 0 <=Int #transferReturn(I) => true 82 | 83 | rule #transferReturn(I) true 84 | 85 | rule 0 <=Int #transferFromReturn(I) => true 86 | 87 | rule #transferFromReturn(I) true 88 | 89 | rule 0 <=Int #status(I) => true 90 | 91 | endmodule 92 | -------------------------------------------------------------------------------- /uniswap/x-y-k.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/verified-smart-contracts/e61ef57de99d07d7182436490f152a14621c5a82/uniswap/x-y-k.pdf --------------------------------------------------------------------------------