Skip to content

Commit e1bf38e

Browse files
authored
Added cast & forge .sh and Dockerfile for release-test (#155)
1 parent eca7795 commit e1bf38e

File tree

5 files changed

+457
-0
lines changed

5 files changed

+457
-0
lines changed

release-test/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*.txt
2+
3+
test/

release-test/Dockerfile

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# https://github.com/paritytech/foundry-polkadot/releases/
2+
3+
FROM ubuntu:24.04 AS builder
4+
5+
ARG VERSION=stable
6+
7+
RUN apt-get update && \
8+
apt-get install -y --no-install-recommends \
9+
build-essential \
10+
ca-certificates \
11+
curl \
12+
git \
13+
&& apt-get clean \
14+
&& rm -rf /var/lib/apt/lists/*
15+
16+
RUN curl -L https://raw.githubusercontent.com/paritytech/foundry-polkadot/refs/heads/master/foundryup/install | bash && \
17+
/root/.foundry/bin/foundryup-polkadot --platform linux --arch amd64 --install ${VERSION}
18+
19+
FROM ubuntu:24.04
20+
21+
RUN apt-get update && \
22+
apt-get install -y --no-install-recommends \
23+
ca-certificates \
24+
git \
25+
&& apt-get clean \
26+
&& rm -rf /var/lib/apt/lists/*
27+
28+
COPY --from=builder /root/.foundry/bin/ /usr/local/bin/

release-test/README.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Polkadot Foundry Release Test Suite
2+
3+
This folder contains scripts and resources for running comprehensive release tests against the [foundry-polkadot](https://github.com/paritytech/foundry-polkadot) toolchain release in a reproducible Docker environment. It is designed to verify the functionality of `forge` and `cast` commands, and to help maintainers validate new releases or changes.
4+
5+
## Limitations of the Test Suite
6+
7+
- **Return Code Only:**
8+
- The scripts in this suite only check that each command returns a zero (0) exit code, indicating success at the process level.
9+
- They do **not** inspect or validate the actual content of the command outputs.
10+
- As a result, a successful run (all commands return 0) does **not** guarantee that all features or commands are working 100% as expected—only that they did not fail fatally.
11+
- For full verification, manual inspection of the output logs (`forge.txt`, `cast.txt`) or more advanced automated output validation would be required.
12+
- **RPC Endpoint Dependency:**
13+
- The reliability and results of the test suite depend on the behavior of the configured RPC URL (e.g., Paseo, Westend, etc.).
14+
- If the RPC endpoint is unstable, down, or changes its behavior, tests may fail or produce inconsistent results, even if the toolchain itself is functioning correctly.
15+
- **Note**: The test suite is currently configured to use the [Paseo](https://testnet-passet-hub-eth-rpc.polkadot.io) RPC endpoint.
16+
17+
## Contents
18+
19+
- **Dockerfile**: Builds a Docker image with the required `foundry-polkadot` binaries. The `version` is configurable as parameter.
20+
- **forge.sh**: Script to run a suite of `forge` commands and capture their output.
21+
- **cast.sh**: Script to run a suite of `cast` commands and capture their output.
22+
- **forge.txt**: Output log from the last run of `forge.sh`.
23+
- **cast.txt**: Output log from the last run of `cast.sh`.
24+
- **test/**: Directory for storing test artifacts.
25+
26+
## Prerequisites
27+
28+
- [Docker](https://docs.docker.com/get-docker/) installed and running.
29+
- [Polkadot Foundry](https://github.com/paritytech/foundry-polkadot/releases/) release available.
30+
31+
## How to Run
32+
33+
### 1. Build the Docker Image
34+
35+
You can specify the Foundry version using the `VERSION` build argument. If omitted, it defaults to `stable`.
36+
37+
```sh
38+
docker build --build-arg VERSION=1.1.0-rc3 -t foundry .
39+
```
40+
41+
Or, to use the default `stable` version:
42+
43+
```sh
44+
docker build -t foundry .
45+
```
46+
47+
### 2. Run the Test Scripts
48+
49+
#### Logical Prerequisites for Test Scripts
50+
51+
- **Forge Test Suite:**
52+
- Requires a wallet to be created in advance, with the address and private key specified in the script (see `ADDRESS` and `PRIVATE_KEY` variables in `forge.sh`).
53+
- The wallet should have sufficient testnet [funds](https://faucet.polkadot.io/?parachain=1111) if you are broadcasting transactions. Currently, the RPC URL is set to the [Passet Hub](https://testnet-passet-hub-eth-rpc.polkadot.io).
54+
55+
- **Cast Test Suite:**
56+
- Requires a previously deployed contract, with its address specified in the script (see `CONTRACT_ADDRESS` in `cast.sh`).
57+
- Also requires a wallet (address and private key) as above.
58+
- The contract should be deployed on the same network as specified by `RPC_URL`.
59+
60+
#### Forge Test Suite
61+
62+
```sh
63+
# chmod +x forge.sh
64+
./forge.sh
65+
```
66+
67+
- This will:
68+
- Build a clean test environment in a Docker container.
69+
- Run a series of `forge` commands (`init`, `build`, `deploy`, etc.).
70+
- Log all output to `forge.txt`.
71+
- Stop on the first error.
72+
73+
#### Cast Test Suite
74+
75+
```sh
76+
# chmod +x cast.sh
77+
./cast.sh
78+
```
79+
80+
- This will:
81+
- Build a clean test environment in a Docker container.
82+
- Run a series of `cast` commands (`wallet`, `call`, `decode`, etc.).
83+
- Log all output to `cast.txt`.
84+
- Stop on the first error.
85+
86+
### 3. Review Results
87+
88+
- Check `forge.txt` and `cast.txt` for command outputs and any errors.
89+
- These files are overwritten on each run.
90+
91+
## Modifying the Release Test
92+
93+
- **To add or change tested commands:**
94+
Edit `forge.sh` or `cast.sh` and add / remove / modify the `docker_run` lines as needed.
95+
Each command is run inside the Docker container and its output is appended to the respective `.txt` file.
96+
97+
- **To change the foundry-polkadot version:**
98+
Pass a different `VERSION` when building the Docker image (see above).
99+
Rebuild the Docker image after making changes:
100+
101+
```sh
102+
docker build --build-arg VERSION=1.1.0-rc4 -t foundry .
103+
```
104+
105+
- **To change the RPC endpoint or test accounts:**
106+
Edit the `RPC_URL`, `ADDRESS`, or `PRIVATE_KEY` variables at the top of the scripts.
107+
108+
## Notes
109+
110+
- If a script fails, check the output log (`forge.txt` or `cast.txt`) for the last successful command and the error message.
111+
- These scripts are intended for CI and release validation, but can also be run locally for manual testing.
112+
- The test suite is destructive to the `test/` directory it creates inside the container; do not use for persistent data.

release-test/cast.sh

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# docker run --rm -it -v $PWD/test:/test -w /test foundry sh
2+
3+
REPOSITORY="test"
4+
5+
> cast.txt
6+
7+
clear
8+
9+
rm -rf $REPOSITORY && mkdir $REPOSITORY
10+
11+
docker_run() {
12+
echo "\033[0;32m> $@\033[0m"
13+
14+
echo "> $@" >> cast.txt
15+
16+
cache=$(mktemp)
17+
18+
docker run --rm -v "$PWD/$REPOSITORY":/"$REPOSITORY" -w /"$REPOSITORY" foundry "$@" > "$cache" 2>&1
19+
20+
status=$?
21+
22+
cat "$cache" | tee -a cast.txt
23+
24+
rm -f "$cache"
25+
26+
if [ $status -ne 0 ]; then
27+
echo "\033[0;31mERROR: Command failed with exit status $status: $@\033[0m"
28+
29+
exit 1
30+
fi
31+
}
32+
33+
ADDRESS="0x2FCDC5f0799ACCb67008aaB9D4AAA08994897997" # based on the output of `cast wallet new`
34+
PRIVATE_KEY="0xf88c374c84378042e20927119c4c8b6ed2d57508c9b8a4f05fe2868ab8f8b73e" # based on the output of `cast wallet new`
35+
36+
# RPC_URL="https://westend-asset-hub-eth-rpc.polkadot.io"
37+
RPC_URL="https://testnet-passet-hub-eth-rpc.polkadot.io"
38+
39+
docker_run cast --version
40+
docker_run forge --version
41+
42+
docker_run forge init .
43+
44+
cat << 'EOF' > $REPOSITORY/foundry.toml
45+
[profile.default]
46+
src = "src"
47+
out = "out"
48+
libs = ["lib"]
49+
50+
[profile.default.resolc]
51+
resolc_compile = true
52+
EOF
53+
54+
CONTRACT=$(docker_run forge create Counter --resolc \
55+
--rpc-url $RPC_URL \
56+
--private-key $PRIVATE_KEY \
57+
--broadcast \
58+
--constructor-args 0
59+
)
60+
echo "$CONTRACT"
61+
CONTRACT_ADDRESS=$(echo "$CONTRACT" | grep 'Deployed to:' | awk '{print $3}')
62+
TRANSACTION_HASH=$(echo "$CONTRACT" | grep 'Transaction hash:' | awk '{print $3}')
63+
64+
docker_run cast 4byte 0xd09de08a
65+
# cast 4byte-calldata
66+
docker_run cast 4byte-event 0xb68ce3d4f35f8b562c4caf11012045e29a80cc1082438f785646ec651416c8d6
67+
docker_run cast abi-encode "increment()"
68+
# cast access-list
69+
docker_run cast address-zero
70+
docker_run cast admin $CONTRACT_ADDRESS \
71+
--rpc-url $RPC_URL
72+
docker_run cast age latest \
73+
--rpc-url $RPC_URL
74+
# cast artifact
75+
docker_run cast balance $ADDRESS \
76+
--rpc-url $RPC_URL
77+
docker_run cast base-fee latest \
78+
--rpc-url $RPC_URL
79+
# cast bind
80+
docker_run cast block latest \
81+
--rpc-url $RPC_URL
82+
docker_run cast block-number latest \
83+
--rpc-url $RPC_URL
84+
docker_run cast call $CONTRACT_ADDRESS "increment()" \
85+
--rpc-url $RPC_URL
86+
docker_run cast calldata "increment()"
87+
docker_run cast chain \
88+
--rpc-url $RPC_URL
89+
docker_run cast chain-id \
90+
--rpc-url $RPC_URL
91+
docker_run cast client \
92+
--rpc-url $RPC_URL
93+
docker_run cast code $CONTRACT_ADDRESS \
94+
--rpc-url $RPC_URL
95+
# cast codehash
96+
docker_run cast codesize $CONTRACT_ADDRESS \
97+
--rpc-url $RPC_URL
98+
# docker_run cast completions zsh
99+
docker_run cast compute-address $ADDRESS \
100+
--rpc-url $RPC_URL
101+
docker_run cast concat-hex 0xa 0xb 0xc
102+
# cast constructor-args
103+
# docker_run cast create2
104+
# cast creation-code
105+
docker_run cast decode-abi "balanceOf(address)(uint256)" 0x000000000000000000000000000000000000000000000000000000000000000a
106+
docker_run cast decode-calldata "transfer(address,uint256)" 0xa9059cbb000000000000000000000000e78388b4ce79068e89bf8aa7f218ef6b9ab0e9d0000000000000000000000000000000000000000000000000008a8e4b1a3d8000
107+
docker_run cast decode-error 0x4e487b710000000000000000000000000000000000000000000000000000000000000011 \
108+
--sig "Panic(uint256)"
109+
docker_run cast decode-event 0x000000000000000000000000000000000000000000000000000000000000002a \
110+
--sig "CounterChanged(int256)"
111+
# cast disassemble
112+
docker_run cast estimate \
113+
--rpc-url $RPC_URL \
114+
--from $ADDRESS \
115+
$CONTRACT_ADDRESS \
116+
"increment()"
117+
docker_run cast find-block $(date +%s) \
118+
--rpc-url $RPC_URL
119+
docker_run cast format-bytes32-string "increment"
120+
docker_run cast format-units 1
121+
docker_run cast from-bin
122+
docker_run cast from-fixed-point 1 1
123+
docker_run cast from-rlp 0x696e6372656d656e740000000000000000000000000000000000000000000000
124+
docker_run cast from-utf8 "increment"
125+
# cast from-wei
126+
docker_run cast gas-price \
127+
--rpc-url $RPC_URL
128+
docker_run cast generate-fig-spec
129+
docker_run cast hash-message "increment"
130+
docker_run cast hash-zero
131+
docker_run cast implementation $CONTRACT_ADDRESS \
132+
--rpc-url $RPC_URL
133+
docker_run cast index string "increment" 1
134+
docker_run cast index-erc7201 1
135+
# cast interface
136+
docker_run cast keccak "increment"
137+
docker_run cast logs \
138+
--rpc-url $RPC_URL \
139+
--address $CONTRACT_ADDRESS \
140+
--from-block 78016
141+
# cast lookup-address
142+
docker_run cast max-int
143+
docker_run cast max-uint
144+
docker_run cast min-int
145+
RAW_TRANSACTION=$(docker_run cast mktx $CONTRACT_ADDRESS "increment()" \
146+
--rpc-url https://testnet-passet-hub-eth-rpc.polkadot.io \
147+
--private-key $PRIVATE_KEY \
148+
--from $ADDRESS \
149+
| grep -E '^0x[0-9a-fA-F]+$'
150+
)
151+
echo "$RAW_TRANSACTION"
152+
docker_run cast decode-transaction $RAW_TRANSACTION
153+
docker_run cast namehash "increment"
154+
docker_run cast nonce $ADDRESS \
155+
--rpc-url $RPC_URL
156+
docker_run cast parse-bytes32-address 0x000000000000000000000000000000000000000000000000000000000000000a
157+
docker_run cast parse-bytes32-string 0x696e6372656d656e740000000000000000000000000000000000000000000000
158+
docker_run cast parse-units 1
159+
docker_run cast pretty-calldata 0xd09de08a
160+
# cast proof
161+
docker_run cast publish $RAW_TRANSACTION \
162+
--rpc-url $RPC_URL
163+
docker_run cast receipt $TRANSACTION_HASH \
164+
--rpc-url $RPC_URL
165+
# cast resolve-name
166+
docker_run cast rpc "eth_getTransactionByHash" $TRANSACTION_HASH \
167+
--rpc-url $RPC_URL
168+
# cast run
169+
# cast selectors
170+
docker_run cast send $CONTRACT_ADDRESS "increment()" \
171+
--rpc-url $RPC_URL \
172+
--private-key $PRIVATE_KEY
173+
docker_run cast shl 1 1
174+
docker_run cast shr 1 1
175+
docker_run cast sig "increment()"
176+
docker_run cast sig-event "increment()"
177+
docker_run cast storage $CONTRACT_ADDRESS 0xc7728314374610455dba288d68795a0a1f4e297598fadddf5234bb036cb803cc \
178+
--rpc-url $RPC_URL
179+
# cast storage-root
180+
docker_run cast to-ascii "0x696e6372656d656e74"
181+
docker_run cast to-base 1 hex
182+
docker_run cast to-bytes32 1
183+
docker_run cast to-check-sum-address $ADDRESS
184+
docker_run cast to-dec 0xff
185+
docker_run cast to-fixed-point 1 1
186+
docker_run cast to-hex 1
187+
docker_run cast to-hexdata 0x1
188+
docker_run cast to-int256 1
189+
docker_run cast to-rlp '["0xaa","0xbb","cc"]'
190+
docker_run cast to-uint256 1
191+
docker_run cast to-unit 1 ether
192+
docker_run cast to-utf8 0x74657374
193+
docker_run cast to-wei 1 ether
194+
docker_run cast tx $TRANSACTION_HASH \
195+
--rpc-url $RPC_URL
196+
# cast tx-pool
197+
docker_run cast upload-signature "transfer(uint256)"
198+
docker_run cast wallet new
199+
docker_run cast wallet new-mnemonic
200+
docker_run cast wallet address \
201+
--private-key $PRIVATE_KEY

0 commit comments

Comments
 (0)