Skip to content

Commit e41b6cd

Browse files
authored
Merge pull request #808 from dapphub/run-tx-bundle
`run-tx` bundles source by default
2 parents f4d0fcf + 75d204f commit e41b6cd

File tree

10 files changed

+177
-72
lines changed

10 files changed

+177
-72
lines changed

.github/workflows/build.yml

+4-1
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,16 @@ jobs:
2020
- uses: actions/checkout@v2
2121
# v12
2222
- uses: cachix/install-nix-action@v12
23+
with:
24+
# https://discourse.nixos.org/t/understanding-binutils-darwin-wrapper-nix-support-bad-substitution/11475/2
25+
nix_path: nixpkgs=channel:nixos-unstable
2326
# v8
2427
- uses: cachix/cachix-action@v8
2528
with:
2629
name: dapp
2730
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
2831
- name: run dapp tests
29-
run: nix-shell --pure src/dapp-tests/shell.nix --command 'make --directory src/dapp-tests'
32+
run: nix-shell --pure src/dapp-tests/shell.nix --command 'make ci --directory src/dapp-tests'
3033
- name: run hevm symbolic tests
3134
run: nix-build -j 1 -A hevm-tests
3235
- run: nix-collect-garbage

src/dapp-tests/Makefile

+4
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,8 @@ test:
22
pytest --hypothesis-show-statistics integration/diff-fuzz.py
33
bash_unit integration/tests.sh
44

5+
ci:
6+
pytest --hypothesis-show-statistics integration/diff-fuzz.py
7+
FUZZ_RUNS=10000 TESTNET_SLEEP=90 bash_unit integration/tests.sh
8+
59
.PHONY: test

src/dapp-tests/integration/tests.sh

+113-53
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,49 @@
11
#! /usr/bin/env bash
22

3-
set -euo pipefail
4-
53
# ------------------------------------------------
64
# CONFIGURATION
75
# ------------------------------------------------
86

9-
FUZZ_RUNS=100
10-
TESTNET_SLEEP=5
7+
export SKIP_SETUP=${SKIP_SETUP:-0}
8+
export FUZZ_RUNS=${FUZZ_RUNS:-100}
9+
export TESTNET_SLEEP=${TESTNET_SLEEP:-5}
10+
export RINKEBY_RPC_URL=${RINKEBY_RPC_URL:-https://rinkeby.infura.io/v3/84842078b09946638c03157f83405213}
11+
export ARCHIVE_NODE_URL=${ARCHIVE_NODE_URL:-https://eth-mainnet.alchemyapi.io/v2/vpeKFsEF6PHifHzdtcwXSDbhV3ym5Ro4}
12+
export ETHERSCAN_API_KEY=${ETHERSCAN_API_KEY:-15IS6MMRAYB19NZN9VHH6H6P57892Z664M}
1113

1214
# ------------------------------------------------
1315
# SHARED SETUP
1416
# ------------------------------------------------
1517

1618
# we spin up a new testnet instance and share it between all tests
1719
setup_suite() {
18-
if [[ -z "$SKIP_SETUP" ]]; then
19-
TMPDIR=$(mktemp -d)
20+
if [[ "$SKIP_SETUP" != 1 ]]; then
21+
export GETHDIR
22+
GETHDIR=$(mktemp -d)
2023

21-
dapp testnet --dir "$TMPDIR" &
24+
dapp testnet --dir "$GETHDIR" &
2225
# give it a few secs to start up
2326
sleep "$TESTNET_SLEEP"
2427

2528
export ETH_RPC_URL="http://127.0.0.1:8545"
26-
export ETH_KEYSTORE="$TMPDIR/8545/keystore"
29+
export ETH_KEYSTORE="$GETHDIR/8545/keystore"
2730
export ETH_PASSWORD=/dev/null
28-
read -r ROOT _ <<< "$(seth ls --keystore "$TMPDIR/8545/keystore")"
31+
read -r ROOT _ <<< "$(seth ls --keystore "$GETHDIR/8545/keystore")"
2932
fi
3033
}
3134

3235
# cleanup the testnet
3336
teardown_suite() {
34-
if [[ -z "$SKIP_SETUP" ]]; then
37+
if [[ "$SKIP_SETUP" != 1 ]]; then
3538
killall geth
36-
rm -rf "$TMPDIR"
39+
rm -rf "$GETHDIR"
3740
fi
3841
}
3942

4043
# ------------------------------------------------
4144
# TEST HELPERS
4245
# ------------------------------------------------
4346

44-
# Tests for resolve-name and lookup-address use a Rinkeby name that's been registered for 100 years and will not be changed
45-
# Infura ID source: https://github.com/ethers-io/ethers.js/blob/0d40156fcba5be155aa5def71bcdb95b9c11d889/packages/providers/src.ts/infura-provider.ts#L17
46-
RINKEBY_RPC_URL=https://rinkeby.infura.io/v3/84842078b09946638c03157f83405213
47-
4847
# generates a new account and gives it some eth, returns the address
4948
fresh_account() {
5049
wei_amount=${1:-$(seth --to-wei 42069 ether)}
@@ -115,43 +114,41 @@ alpha() {
115114
# `seth run-tx`
116115
# `hevm exec`
117116
test_smoke() {
118-
local account
117+
local account bytecode
119118
account=$(fresh_account)
119+
bytecode=$(mktemp -d)
120120

121121
# Deploy a simple contract:
122-
solc --bin --bin-runtime "$CONTRACTS/stateful.sol" -o "$TMPDIR"
122+
solc --bin --bin-runtime "$CONTRACTS/stateful.sol" -o "$bytecode"
123123

124-
A_ADDR=$(seth send --create "$(<"$TMPDIR"/A.bin)" "constructor(uint y)" 1 --from "$account" --keystore "$TMPDIR"/8545/keystore --password /dev/null --gas 0xffffff)
124+
A_ADDR=$(seth send --create "$(<"$bytecode"/A.bin)" "constructor(uint y)" 1 --from "$account" --gas 0xffffff)
125125

126126
# Compare deployed code with what solc gives us
127-
assert_equals 0x"$(cat "$TMPDIR"/A.bin-runtime)" "$(seth code "$A_ADDR")"
127+
assert_equals 0x"$(cat "$bytecode"/A.bin-runtime)" "$(seth code "$A_ADDR")"
128128

129129
# And with what hevm gives us
130130
EXTRA_CALLDATA=$(seth --to-uint256 1)
131-
HEVM_RET=$(hevm exec --code "$(<"$TMPDIR"/A.bin)""${EXTRA_CALLDATA/0x/}" --gas 0xffffff)
131+
HEVM_RET=$(hevm exec --code "$(<"$bytecode"/A.bin)""${EXTRA_CALLDATA/0x/}" --gas 0xffffff)
132132

133133
assert_equals "$HEVM_RET" "$(seth code "$A_ADDR")"
134134

135-
TX=$(seth send "$A_ADDR" "off()" --gas 0xffff --password /dev/null --from "$account" --keystore "$TMPDIR"/8545/keystore --async)
135+
TX=$(seth send "$A_ADDR" "off()" --gas 0xffff --password /dev/null --from "$account" --async)
136136

137137
# since we have one tx per block, seth run-tx and seth debug are equivalent
138-
assert_equals 0x "$(seth run-tx "$TX")"
138+
assert_equals 0x "$(seth run-tx "$TX" --no-src)"
139139

140140
# dynamic fee transactions (EIP-1559)
141141
seth send "$A_ADDR" "on()" \
142142
--gas 0xffff \
143143
--password /dev/null \
144144
--from "$account" \
145-
--keystore "$TMPDIR"/8545/keystore \
146145
--prio-fee 2gwei \
147146
--gas-price 10gwei
148147

149-
B_ADDR=$(seth send \
150-
--create 0x647175696e6550383480393834f3 \
148+
B_ADDR=$(seth send --create 0x647175696e6550383480393834f3 \
151149
--gas 0xffff \
152150
--password /dev/null \
153-
--from "$ACC" \
154-
--keystore "$TMPDIR"/8545/keystore \
151+
--from "$account" \
155152
--prio-fee 2gwei \
156153
--gas-price 10gwei)
157154

@@ -161,28 +158,28 @@ test_smoke() {
161158
# checks that seth send works with both checksummed and unchecksummed addresses
162159
test_seth_send_address_formats() {
163160
local account
164-
account=$(fresh_account)
161+
acc=$(fresh_account)
165162

166-
lower=$(echo "$account" | tr '[:upper:]' '[:lower:]')
163+
lower=$(echo "$acc" | tr '[:upper:]' '[:lower:]')
167164
export ETH_GAS=0xffff
168165

169166
# with checksummed
170-
tx=$(seth send "$ZERO" --from "$ACC" --password /dev/null --value "$(seth --to-wei 1 ether)" --keystore "$TMPDIR"/8545/keystore --async)
167+
tx=$(seth send "$ZERO" --from "$acc" --password /dev/null --value "$(seth --to-wei 1 ether)" --async)
171168
assert_equals "$lower" "$(seth tx "$tx" from)"
172169

173170
# without checksum
174-
tx=$(seth send "$ZERO" --from "$lower" --password /dev/null --value "$(seth --to-wei 1 ether)" --keystore "$TMPDIR"/8545/keystore --async)
171+
tx=$(seth send "$ZERO" --from "$lower" --password /dev/null --value "$(seth --to-wei 1 ether)" --async)
175172
assert_equals "$lower" "$(seth tx "$tx" from)"
176173

177174
# try again with eth_rpc_accounts
178175
export ETH_RPC_ACCOUNTS=true
179176

180177
# with checksummed
181-
tx=$(seth send "$ZERO" --from "$ACC" --password /dev/null --value "$(seth --to-wei 1 ether)" --keystore "$TMPDIR"/8545/keystore --async)
178+
tx=$(seth send "$ZERO" --from "$acc" --password /dev/null --value "$(seth --to-wei 1 ether)" --async)
182179
assert_equals "$lower" "$(seth tx "$tx" from)"
183180

184181
# without checksum
185-
tx=$(seth send "$ZERO" --from "$lower" --password /dev/null --value "$(seth --to-wei 1 ether)" --keystore "$TMPDIR"/8545/keystore --async)
182+
tx=$(seth send "$ZERO" --from "$lower" --password /dev/null --value "$(seth --to-wei 1 ether)" --async)
186183
assert_equals "$lower" "$(seth tx "$tx" from)"
187184
}
188185

@@ -192,27 +189,27 @@ test_hevm_symbolic() {
192189

193190
solc --bin-runtime -o . --overwrite "$CONTRACTS/factor.sol"
194191
# should find counterexample
195-
hevm symbolic --code "$(<A.bin-runtime)" --sig "factor(uint x, uint y)" --smttimeout 40000 --solver cvc4 && error || echo "hevm success: found counterexample"
196-
hevm symbolic --code "$(<"$CONTRACTS/dstoken.bin-runtime")" --sig "transferFrom(address, address, uint)" --get-models
192+
hevm symbolic --code "$(<A.bin-runtime)" --sig "factor(uint x, uint y)" --smttimeout 40000 --solver cvc4 && fail || echo "hevm success: found counterexample"
193+
hevm symbolic --code "$(<"$CONTRACTS/dstoken.bin-runtime")" --sig "transferFrom(address, address, uint)" --get-models &> /dev/null || fail
197194

198195
solc --bin-runtime -o . --overwrite "$CONTRACTS/token.sol"
199196
# This one explores all paths (cvc4 is better at this)
200-
hevm symbolic --code "$(<Token.bin-runtime)" --solver cvc4
197+
hevm symbolic --code "$(<Token.bin-runtime)" --solver cvc4 || fail
201198

202199
# The contracts A and B should be equivalent:
203200
solc --bin-runtime -o . --overwrite "$CONTRACTS/AB.sol"
204-
hevm equivalence --code-a "$(<A.bin-runtime)" --code-b "$(<B.bin-runtime)" --solver cvc4
201+
hevm equivalence --code-a "$(<A.bin-runtime)" --code-b "$(<B.bin-runtime)" --solver cvc4 || fail
205202
}
206203

207204
test_custom_solc_json() {
208-
TMPDIR=$(mktemp -d)
205+
tmp=$(mktemp -d)
209206

210207
# copy source file
211-
mkdir -p "$TMPDIR/src"
212-
cp "$CONTRACTS/factor.sol" "$TMPDIR/src"
208+
mkdir -p "$tmp/src"
209+
cp "$CONTRACTS/factor.sol" "$tmp/src"
213210

214211
# init dapp project
215-
cd "$TMPDIR" || exit
212+
cd "$tmp" || exit
216213
export GIT_CONFIG_NOSYSTEM=1
217214
export GIT_AUTHOR_NAME=dapp
218215
@@ -256,15 +253,15 @@ test_block_1() {
256253
}
257254

258255
test_decimal_roundtrip() {
259-
for _ in $(seq $FUZZ_RUNS); do
256+
for _ in $(seq "$FUZZ_RUNS"); do
260257
local input
261258
input=$(uint256)
262259
assert_equals "$input" "$(seth --to-dec "$(seth --to-hex "$input")")"
263260
done
264261
}
265262

266263
test_hex_roundtrip() {
267-
for _ in $(seq $FUZZ_RUNS); do
264+
for _ in $(seq "$FUZZ_RUNS"); do
268265
local input
269266
input="0x$(bytes32)"
270267
lower=$(echo "$input" | tr '[:upper:]' '[:lower:]')
@@ -273,22 +270,25 @@ test_hex_roundtrip() {
273270
}
274271

275272
test_to_fix_roundtrip() {
276-
for _ in $(seq $FUZZ_RUNS); do
273+
for _ in $(seq "$FUZZ_RUNS"); do
277274
local input digits
278275
input="$(uint256)"
279-
digits="$(mod "$(uint8)" 77)" # 78 decimal digits in max uint256
276+
277+
length="${#input}"
278+
digits="$(mod "$(uint8)" "$length")"
279+
280280
assert_equals "$input" "$(seth --from-fix "$digits" "$(seth --to-fix "$digits" "$input")")"
281281
done
282282
}
283283

284284
test_from_fix_roundtrip() {
285-
for _ in $(seq $FUZZ_RUNS); do
285+
for _ in $(seq "$FUZZ_RUNS"); do
286286
local input digits
287287
input="$(uint256)"
288+
288289
length="${#input}"
289-
digits="$(mod "$(uint8)" 77)" # 78 decimal digits in max uint256
290+
digits="$(mod "$(uint8)" "$length")"
290291

291-
[[ $digits -ge $length ]] && continue
292292
whole_digits=$(bc <<< "$length - $digits" | tr -d '\\\n')
293293
input="${input:0:whole_digits}.${input:$whole_digits:$length}"
294294

@@ -516,21 +516,21 @@ test_resolve_name1() {
516516

517517
test_resolve_name2() {
518518
assert_equals \
519-
"$(seth resolve-name seth-test.eth --rpc-url=$RINKEBY_RPC_URL)" \
520-
"$(seth resolve-name sEtH-tESt.etH --rpc-url=$RINKEBY_RPC_URL)"
519+
"$(seth resolve-name seth-test.eth --rpc-url="$RINKEBY_RPC_URL")" \
520+
"$(seth resolve-name sEtH-tESt.etH --rpc-url="$RINKEBY_RPC_URL")"
521521
}
522522

523523
test_lookup_address1() {
524524
# using example from ethers docs: https://docs.ethers.io/v5/single-page/#/v5/api/providers/provider/-%23-Provider-lookupAddress
525525
local output
526-
output=$(seth lookup-address 0x49c92F2cE8F876b070b114a6B2F8A60b83c281Ad --rpc-url=$RINKEBY_RPC_URL)
526+
output=$(seth lookup-address 0x49c92F2cE8F876b070b114a6B2F8A60b83c281Ad --rpc-url="$RINKEBY_RPC_URL")
527527
assert_equals "seth-test.eth" "$output"
528528
}
529529

530530
test_lookup_address2() {
531531
assert_equals \
532-
"$(seth lookup-address 0x49c92F2cE8F876b070b114a6B2F8A60b83c281Ad --rpc-url=$RINKEBY_RPC_URL)" \
533-
"$(seth lookup-address 0x49c92f2ce8f876b070b114a6b2f8a60b83c281ad --rpc-url=$RINKEBY_RPC_URL)"
532+
"$(seth lookup-address 0x49c92F2cE8F876b070b114a6B2F8A60b83c281Ad --rpc-url="$RINKEBY_RPC_URL")" \
533+
"$(seth lookup-address 0x49c92f2ce8f876b070b114a6b2f8a60b83c281ad --rpc-url="$RINKEBY_RPC_URL")"
534534
}
535535

536536
# SETH 4BYTE TESTS
@@ -573,3 +573,63 @@ test_to_fix3() {
573573
test_to_fix4() {
574574
assert_equals 1.234567890000000000 "$(seth --to-fix 18 1234567890000000000)"
575575
}
576+
577+
# SETH RUN-TX TESTS
578+
test_run_tx_source_fetching() {
579+
export ETH_RPC_URL=$ARCHIVE_NODE_URL
580+
local out err
581+
out=$(mktemp)
582+
err=$(mktemp)
583+
584+
# prints a message when source is not available
585+
seth run-tx 0xc1511d7fcc498ae8236a18a67786701e6980dcf641b72bcfd4c2a3cd45fb209c --trace 1> "$out" 2> "$err"
586+
assert "grep -q 'Contract source code not verified' $err" 1
587+
assert "grep -q 'delegatecall 0xAa1c1B3BbbB59930a4E88F87345B8C513cc56Fa6::0x526327f2' $err" 2
588+
assert_equals "0x188fffa3a6cd08bdcc3d5bf4add2a2c0ac5e9d94a278ea1630187b3da583a1f0" "$(cat "$out")"
589+
590+
local prefiles
591+
prefiles=$(ls)
592+
593+
# seth pulls from etherscan by default (flattened)
594+
seth run-tx 0x41ccbab4d7d0cd55f481df7fce449986364bf13e655dddfb30aa9b38a4340db7 --trace 1> "$out" 2> "$err"
595+
assert "grep -q 'UniswapV2Pair@0x28d2DF1E3481Ba90D75E14b9C02cea85b7d6FA2C' $err" 3
596+
assert "grep -q 'PairCreated(UniswapV2Pair@0x28d2DF1E3481Ba90D75E14b9C02cea85b7d6FA2C, 51691)' $err" 4
597+
assert_equals "0x00000000000000000000000028d2df1e3481ba90d75e14b9c02cea85b7d6fa2c" "$(cat "$out")"
598+
599+
# seth does not write any files to the cwd
600+
assert_equals "$prefiles" "$(ls)"
601+
602+
# seth pulls from etherscan by default (stdjson)
603+
seth run-tx 0x5da4bf1e5988cf94fd96d2c1dd3f420d2cea1aebe8d1e1c10dd9fe78a2147798 --trace 1> "$out" 2> "$err"
604+
assert "grep -q 'ownerOf' $err" 5
605+
assert "grep -q 'iFeather@0xD1edDfcc4596CC8bD0bd7495beaB9B979fc50336' $err" 6
606+
assert_equals "0x" "$(cat "$out")"
607+
608+
# seth does not write any files to the cwd
609+
assert_equals "$prefiles" "$(ls)"
610+
611+
# seth does not pull from etherscan if --source is passed
612+
seth run-tx 0x41ccbab4d7d0cd55f481df7fce449986364bf13e655dddfb30aa9b38a4340db7 --trace --source /dev/null 1> "$out" 2> "$err"
613+
assert "grep -q 'call 0x28d2DF1E3481Ba90D75E14b9C02cea85b7d6FA2C::0x485cc9550000000000000000000000007fa7df4' $err" 7
614+
assert "grep -q 'log3(0xd3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9, 0xffffffffffffffff' $err" 8
615+
assert_equals "0x00000000000000000000000028d2df1e3481ba90d75e14b9c02cea85b7d6fa2c" "$(cat "$out")"
616+
617+
# seth does not pull from etherscan if --no-src is passed at the command line
618+
seth run-tx 0x41ccbab4d7d0cd55f481df7fce449986364bf13e655dddfb30aa9b38a4340db7 --trace --no-src 1> "$out" 2> "$err"
619+
assert "grep -q 'call 0x28d2DF1E3481Ba90D75E14b9C02cea85b7d6FA2C::0x485cc9550000000000000000000000007fa7df4' $err" 9
620+
assert "grep -q 'log3(0xd3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9, 0xffffffffffffffff' $err" 10
621+
assert_equals "0x00000000000000000000000028d2df1e3481ba90d75e14b9c02cea85b7d6fa2c" "$(cat "$out")"
622+
623+
# seth does not pull from etherscan if SETH_NOSRC is set to "yes"
624+
SETH_NOSRC=yes seth run-tx 0x41ccbab4d7d0cd55f481df7fce449986364bf13e655dddfb30aa9b38a4340db7 --trace 1> "$out" 2> "$err"
625+
assert "grep -q 'call 0x28d2DF1E3481Ba90D75E14b9C02cea85b7d6FA2C::0x485cc9550000000000000000000000007fa7df4' $err" 11
626+
assert "grep -q 'log3(0xd3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9, 0xffffffffffffffff' $err" 12
627+
assert_equals "0x00000000000000000000000028d2df1e3481ba90d75e14b9c02cea85b7d6fa2c" "$(cat "$out")"
628+
629+
# seth does not pull from etherscan if ETHERSCAN_API_KEY is unset
630+
unset ETHERSCAN_API_KEY
631+
seth run-tx 0x41ccbab4d7d0cd55f481df7fce449986364bf13e655dddfb30aa9b38a4340db7 --trace 1> "$out" 2> "$err"
632+
assert "grep -q 'call 0x28d2DF1E3481Ba90D75E14b9C02cea85b7d6FA2C::0x485cc9550000000000000000000000007fa7df4' $err" 13
633+
assert "grep -q 'log3(0xd3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9, 0xffffffffffffffff' $err" 14
634+
assert_equals "0x00000000000000000000000028d2df1e3481ba90d75e14b9c02cea85b7d6fa2c" "$(cat "$out")"
635+
}

src/dapp-tests/shell.nix

+21-1
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,25 @@ in
1414

1515
mkShell {
1616
name = "dapp-tests";
17-
buildInputs = [ killall bash_unit cacert bashInteractive curl dapp gnumake hevm procps seth solc go-ethereum python-with-pkgs ];
17+
buildInputs = [
18+
bashInteractive
19+
bash_unit
20+
bc
21+
cacert
22+
coreutils
23+
curl
24+
dapp
25+
gnumake
26+
go-ethereum
27+
hevm
28+
jq
29+
killall
30+
procps
31+
python-with-pkgs
32+
seth
33+
solc
34+
util-linux
35+
which
36+
];
37+
LANG="en_US.UTF-8";
1838
}

0 commit comments

Comments
 (0)