Working Foundry

This commit is contained in:
Abdul Rabbani 2022-03-14 15:16:12 -04:00
parent 90c8985375
commit df55a62430
13 changed files with 205 additions and 62 deletions

1
.gitignore vendored
View File

@ -48,3 +48,4 @@ profile.cov
**/yarn-error.log
foundry/deployments/local-private-network/geth-linux-amd64
foundry/projects/local-private-network/geth-linux-amd64

59
foundry/README.md Normal file
View File

@ -0,0 +1,59 @@
# Foundry README
# Overview
This document will go through the steps needed to test using Foundry. Currently, we use Foundry in the following capacity.
1. Create a private network with our internal version of Geth.
2. Deploy a smart contract to the private network.
3. Test the smart contract on the private network.
4. Create a transaction on the private network.
# Steps
The steps to create a new project are as follows.
## 1. Creating New Project
1. `cd foundry/projects`.
2. Create a directory that captures your project: `mkdir local-private-network; cd local-private-network`.
3. Create a [new foundry project](https://onbjerg.github.io/foundry-book/forge/creating-a-new-project.html): `forge init stateful`.
4. Follow the foundry [documentation](https://onbjerg.github.io/foundry-book/forge/tests.html) for writing smart contract tests.
## 2. Deployments
You can choose to have custom deployments for your workflow. However, it is recommended to utilize Docker.
# Existing Projects
Below, you can find existing projects and their descriptions.
## `local-private-network`
The purpose of this project is as follows:
1. Compile the geth from the local source.
2. Build a docker container with `ipld-eth-db` and another container for the `local-private-network`.
3. Run the compiled version of geth.
4. Deploy a smart contract to the private blockchain.
5. Trigger a transaction on the newly deployed smart contract.
## Using This Project
If you want to test your local geth code, do the following:
1. cd `foundry/projects/local-private-network`.
2. `./wrapper.sh` - This script will do all the heavy lifting for you.
3. Keep an eye out for the outputs from the docker container.
4. Enter the docker container and do as you please.
5. If you want to change your geth code, you will have to run `./wrapper.sh` for subsequent runs.
6. If you do not change your geth code, you have to run: `docker-compose up --build`.
### Key Notes:
- The command to [deploy](https://onbjerg.github.io/foundry-book/forge/deploying.html) the smart contract is: `forge create --keystore $ETH_KEYSTORE_FILE --rpc-url [http://127.0.0.1:8545](http://127.0.0.1:8545/) --constructor-args 1 --password "" --legacy /root/stateful/src/Stateful.sol:Stateful`
- The command to interact create a [transaction](https://onbjerg.github.io/foundry-book/reference/cast.html) is: `cast send --keystore $ETH_KEYSTORE_FILE --rpc-url [http://127.0.0.1:8545](http://127.0.0.1:8545/) --password "" --legacy $DEPLOYED_ADDRESS "off()"`
- The `Dockerfile` compiles `cast` and `forge`.
- The `foundry/projects/local-private-network/deploy-local-network.sh` file does most heavy lifting. It spins up geth and triggers various events.
- The `foundry/projects/local-private-network/start-private-network.sh` file triggers `deploy-local-network.sh`. This file runs all the tests.
- The `geth` node will stay running even after the tests are terminated.

View File

@ -1,21 +0,0 @@
FROM frolvlad/alpine-bash
RUN apk update ; apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing/ --allow-untrusted ca-certificates curl bash git jshon jq
#USER guest
WORKDIR /root
# copy all files
ADD ./deploy-local-network.sh .
ADD ./geth-linux-amd64 /bin/geth
ADD ./start-private-network.sh .
RUN curl -L https://foundry.paradigm.xyz | bash; \
/bin/bash -c 'source $HOME/.bashrc'; \
/root/.foundry/bin/foundryup
RUN chmod +x /bin/geth
EXPOSE 8545
EXPOSE 8546
ENTRYPOINT ["./start-private-network.sh"]

View File

@ -1,36 +0,0 @@
#!/bin/bash
set -ex
# clean up
trap 'killall geth && rm -rf "$TMPDIR"' EXIT
trap "exit 1" SIGINT SIGTERM
TMPDIR=$(mktemp -d)
/bin/bash deploy-local-network.sh --rpc-addr 0.0.0.0 --chain-id 4 --db-user $DB_USER --db-password $DB_PASSWORD --db-name $DB_NAME \
--db-host $DB_HOST --db-port $DB_PORT --db-write $DB_WRITE --dir "$TMPDIR" --address $ADDRESS \
--db-type $DB_TYPE --db-driver $DB_DRIVER --db-waitforsync $DB_WAIT_FOR_SYNC &
echo "sleeping 90 sec"
# give it a few secs to start up
sleep 90
#read -r ACC BAL <<< "$(seth ls --keystore "$TMPDIR/8545/keystore")"
#echo $ACC
#echo $BAL
#
#
## Deploy a contract:
#solc --bin --bin-runtime docker/stateful.sol -o "$TMPDIR"
#A_ADDR=$(seth send --create "$(<"$TMPDIR"/A.bin)" "constructor(uint y)" 1 --from "$ACC" --keystore "$TMPDIR"/8545/keystore --password /dev/null --gas 0xfffffff)
#
#echo $A_ADDR
#
## Call transaction
#
#TX=$(seth send "$A_ADDR" "off()" --gas 0xffff --password /dev/null --from "$ACC" --keystore "$TMPDIR"/8545/keystore --async)
#echo $TX
#RESULT=$(seth run-tx "$TX")
#echo $RESULT
# Run forever
tail -f /dev/null

View File

@ -0,0 +1,37 @@
FROM frolvlad/alpine-bash
# copy all files
RUN apk update ; apk add --no-cache --allow-untrusted ca-certificates curl bash git jq
ENV GLIBC_REPO=https://github.com/sgerrand/alpine-pkg-glibc
ENV GLIBC_VERSION=2.35-r0
RUN set -ex && \
apk --update add libstdc++ curl ca-certificates && \
for pkg in glibc-${GLIBC_VERSION} glibc-bin-${GLIBC_VERSION}; \
do curl -sSL ${GLIBC_REPO}/releases/download/${GLIBC_VERSION}/${pkg}.apk -o /tmp/${pkg}.apk; done && \
apk add --allow-untrusted /tmp/*.apk ; \
rm -v /tmp/*.apk ;/usr/glibc-compat/sbin/ldconfig /lib /usr/glibc-compat/lib
RUN apk add gcompat; echo "Sorry"
WORKDIR /root
COPY stateful ./stateful
ADD ./start-private-network.sh .
ADD ./deploy-local-network.sh .
ADD ../../geth-linux-amd64 /bin/geth
RUN curl -L https://foundry.paradigm.xyz | bash; \
/bin/bash -c 'source $HOME/.bashrc'; \
/root/.foundry/bin/foundryup
ENV PATH "$PATH:/root/.foundry/bin/"
RUN echo "export PATH=${PATH}" >> $HOME/.bashrc;
RUN chmod +x /bin/geth
EXPOSE 8545
EXPOSE 8546
ENTRYPOINT ["./start-private-network.sh"]

View File

@ -9,8 +9,8 @@ start_path=$(pwd)
cd ../../../
echo -e "${GREEN}Building geth!${NC}"
docker build -t vulcanize/go-ethereum -f Dockerfile .
docker run --rm --entrypoint cat vulcanize/go-ethereum /usr/local/bin/geth > foundry/deployments/local-private-network/geth-linux-amd64
chmod +x foundry/deployments/local-private-network/geth-linux-amd64
docker run --rm --entrypoint cat vulcanize/go-ethereum /usr/local/bin/geth > foundry/projects/local-private-network/geth-linux-amd64
chmod +x foundry/projects/local-private-network/geth-linux-amd64
echo -e "${GREEN}geth build complete!${NC}"
cd $start_path

View File

@ -1,8 +1,8 @@
#!/bin/bash
set -e
OPTS="dapp testnet [<options>] <args>...
dapp testnet --help
OPTS="./deploy-local-network.sh [<options>] <args>...
./deploy-local-network.sh --help
--
db-user=name database user
db-password=password database password
@ -184,4 +184,4 @@ printf 'dapp-testnet: Account: %s (default)\n' "${address[0]}" >&2
[[ "${#address[@]}" -gt 1 ]] && printf 'dapp-testnet: Account: %s\n' "${address[@]:1}" >&2
while true; do sleep 3600; done
while true; do sleep 3600; done

View File

@ -0,0 +1,50 @@
#!/bin/bash
set -ex
# clean up
trap 'killall geth && rm -rf "$TMPDIR"' EXIT
trap "exit 1" SIGINT SIGTERM
TMPDIR=$(mktemp -d)
/bin/bash deploy-local-network.sh --rpc-addr 0.0.0.0 --chain-id 4 --db-user $DB_USER --db-password $DB_PASSWORD --db-name $DB_NAME \
--db-host $DB_HOST --db-port $DB_PORT --db-write $DB_WRITE --dir "$TMPDIR" --address $ADDRESS \
--db-type $DB_TYPE --db-driver $DB_DRIVER --db-waitforsync $DB_WAIT_FOR_SYNC &
echo "sleeping 90 sec"
# give it a few secs to start up
sleep 90
# Run tests
cd stateful
forge build
forge test --fork-url http://localhost:8545
# Deploy contracts
ETH_KEYSTORE_FILES=()
echo "ETH KEYSTORE: $TMPDIR/8545/keystore"
for entry in `ls $TMPDIR/8545/keystore`; do
ETH_KEYSTORE_FILES+=("${TMPDIR}/8545/keystore/${entry}")
done
echo "ETH_KEYSTORE_FILES: $ETH_KEYSTORE_FILES"
ETH_KEYSTORE_FILE=${ETH_KEYSTORE_FILES[0]}
if [ "${#ETH_KEYSTORE_FILES[@]}" -eq 1 ]; then
echo "Only one KEYSTORE"
else
echo "WARNING: More than one file in keystore: ${ETH_KEYSTORE_FILES}"
fi
DEPLOYED_ADDRESS=$(forge create --keystore $ETH_KEYSTORE_FILE --rpc-url http://127.0.0.1:8545 --constructor-args 1 --password "" --legacy /root/stateful/src/Stateful.sol:Stateful | grep "Deployed to:" | cut -d " " -f 3)
echo "Contract has been deployed to: $DEPLOYED_ADDRESS"
# Call a transaction
TX_OUT=$(cast send --keystore $ETH_KEYSTORE_FILE --rpc-url http://127.0.0.1:8545 --password "" --legacy $DEPLOYED_ADDRESS "off()")
echo "TX OUTPUT: $TX_OUT"
# Run forever
tail -f /dev/null

View File

@ -0,0 +1,7 @@
[default]
src = 'src'
out = 'out'
libs = ['lib']
remappings = ['ds-test/=lib/ds-test/src/']
# See more config options https://github.com/gakonst/foundry/tree/master/config

View File

@ -0,0 +1,20 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;
contract Stateful {
uint x;
constructor(uint y) public {
x = y;
}
function off() public {
require(x == 1);
x = 0;
}
function on() public {
require(x == 0);
x = 1;
}
}

View File

@ -0,0 +1,19 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;
import "ds-test/test.sol";
import {Stateful} from "../Stateful.sol";
contract StatefulTest is DSTest {
Stateful contractA;
//contractA A;
uint x;
function setUp() public {
x = 1;
contractA = new Stateful(x);
}
function testExample() public {
contractA.off();
}
}

View File

@ -0,0 +1,7 @@
#!/bin/bash
# This script will run everthing for you. Sit back and enjoy they show.
set -e
./compile-geth.sh
docker-compose up --build