Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/lambdaclass/ethereum_war_game_tooling
We are slow while using the UI/UX of crypto wallets so we created our CLI version
https://github.com/lambdaclass/ethereum_war_game_tooling
ctf-challenges distributed-systems ethereum wargame
Last synced: 26 days ago
JSON representation
We are slow while using the UI/UX of crypto wallets so we created our CLI version
- Host: GitHub
- URL: https://github.com/lambdaclass/ethereum_war_game_tooling
- Owner: lambdaclass
- License: mit
- Created: 2022-02-17T13:04:48.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2022-07-21T17:30:36.000Z (over 2 years ago)
- Last Synced: 2024-07-30T21:01:19.348Z (4 months ago)
- Topics: ctf-challenges, distributed-systems, ethereum, wargame
- Language: Elixir
- Homepage:
- Size: 638 KB
- Stars: 5
- Watchers: 4
- Forks: 2
- Open Issues: 36
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Ethereum War Game and CTF Tooling
## EthClient
Simple elixir client to interact with the ethereum blockchain, deploying and calling smart contracts.
## Requirements
- Erlang/OTP 24
- Elixir 1.13.0
- Rust 1.58.0
- [Geth](https://geth.ethereum.org/docs/install-and-build/installing-geth)## Quick Start with Tilt
*"I just want to try it right now!!"*
Run the following commands to get started. This will configure and start both Ethereum nodes, the Livebook server and the EthClient Elixir application.
```bash
git clone [email protected]:lambdaclass/ethereum_war_game_tooling.git
cd ethereum_war_game_tooling
tilt up
```
Now that you have everything ready you can start playing with the tool in **one of two ways**.#### Livebook
Accesing to the Application running at http://localhost:8080 and creating a new notebook.#### Elixir IEx terminal
```bash
cd eth_client
make tilt.up
```### Configuration
All global configuration is kept in the `EthClient.Context` module, which holds the following values:
- `rpc_host`: The hostname needed to interact with the ethereum Json RPC API. This can be an infura-type url or just the hostname of an actual node.
- `chain_id`: The id of the chain currently in use (`1` for mainnet, `4` for Rinkeby, etc).
- `user_account`: A value of type `EthClient.Account`, which holds two fields, `address` and `private_key`. This is the account used to sign and send all transactions.
- `contract`: A value of type `EthClient.Contract`, which holds two fields, `address` and `functions`.You can change any of these config values at runtime by using the functions exposed by the `EthClient.Context` module.
The default config assumes you're running the local ethereum network this repo provides.
If you want to use infura-type host this are the setps you must follow:
First set your infura api key
```
Context.set_infura_api_key("your_infura_api_key")
```Then set the your etherscan api key
```
Context.set_etherscan_api_key("your_eth_scan_api_key")
```And finally set the name of the chain you want to use, for now this are the supported chains: eht mainnet, rinkeby and ropsten.
```
EthClient.set_chain("chain_name")
```### Interacting with smart contracts
#### Without an ABI file
Currently there are three functions in the `EthClient` module that form the main API:- `EthClient.deploy(bin_path)` deploys a compiled smart contract given a path to its `.bin` file, generated by compiling said contract (i.e. by running something like `solc --bin contract.sol`). After a successful deployment, the context will be updated to use it.
- `EthClient.call(method, arguments)` calls any read-only public method of a contract.
- `EthClient.invoke(method, arguments, amount)` calls any public method of a contract that requires a transaction (usually to write stuff to the blockchain). The `amount` parameter controls how much `eth` is sent to the contract.
#### With an ABI file
When there is an `.abi` file with the ABI of the contract, user can interact with API in a different way:- `EthClient.deploy(bin_path, abi_path)` deploys a compiled smart contract (as it is explained in [Without an ABI file](#without_an_abi) section) but it also add contract functions to the context when deploying it.
- Then, user can interact with contract functions by calling `Context.contract.functions.contract_function_name.(parameters)`, either if it is a read-only method or not.
### Example
When running `iex -S mix`, there will be a default `bin_path` variable loaded with the path to a compiled `Storage` contract and a default `abi_path` variable with the path to contract's ABI. You can then immediately deploy it with
```
EthClient.deploy(bin_path)
```and then call each of its functions. If you're running the local ethereum network, you should see something like the following:
```
iex(1)> EthClient.deploy(bin_path)
19:53:26.918 [info] Deployment transaction accepted by the network, tx_hash: 0x14765466533a85c90ce45dd966854dc5fb95543ba97f343f389872c64ed9597b
19:53:26.922 [info] Waiting for confirmation...
19:53:28.931 [info] Contract deployed, address: 0x69148897094941cfad7fd3d52c5e1a810ba4e123 Current contract updated
:ok
``````
iex(2)> EthClient.call("test_function()", [])
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000001"}
``````
iex(3)> EthClient.invoke("store(uint256)", [20], 0)
19:55:28.127 [info] Transaction accepted by the network, tx_hash: 0x137320dcfb61055313f73aafa799670a4d172936bc91200ebf7a95092f77c297
19:55:28.127 [info] Waiting for confirmation...
19:55:41.177 [info] Transaction confirmed!
{:ok, "0x137320dcfb61055313f73aafa799670a4d172936bc91200ebf7a95092f77c297"}
``````
iex(4)> EthClient.call("retrieve()", [])
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000014"}
```## Local nodes
Install dependencies with```
make init
```then source your `.bashrc`, `.zshrc` or similar files to add foundry to your `PATH`, then run `foundryup` to install `forge` and `cast`.
To run two local Ethereum nodes:
```
cd geth_nodes
make setup
make up
```## Accounts
You can use the miner accounts to pay for transactions.Node 1 miner account
- Address: `0xafb72ccaeb7e22c8a7640f605824b0898424b3da`
- Private key: `e90d75baafee04b3d9941bd8d76abe799b391aec596515dee11a9bd55f05709c`Node 2 miner account:
- Address: `0x77b648683cde1d69544ed6f4f7204e8d51c324db`
- Private key: `f71d3dd32649f9bdfc8e4a5232d3f245860243756f96fbe070c31fc44c9293f4`## Test contract
You can then deploy the test contract with
```
make deploy_test_contract
```under the root directory.
The code for this contract is in `contracts/src/Storage.sol`; it has 3 functions: `test_function` will always return `1`, `store(uint256)` stores the given number and `retrieve()` returns said number.
The output should look like this
```
forge create --rpc-url http://127.0.0.1:8545 Storage --root contracts/ --private-key df57089febbacf7ba0bc227dafbffa9fc08a93fdc68e1e42411a14efcf23656e
compiling...
Compiling 1 files with 0.8.10
Compilation finished successfully
Compiler run successful
success.
Deployer: 0x8626f6940e2eb28930efb4cef49b2d1f2c9c1199
Deployed to: 0xb581c9264f59bf0289fa76d61b2d0746dce3c30d
Transaction hash: 0xe2c19a2f0766c0e00c416433a8cf53c9993fc918e2b321f348d8de421c195416
```Take note of the address you are given after `Deployed to:`, as that is the contract's address in the local chain.
With it, you can now call its test function using `cast` like this:```
cast call "test_function()(uint256)" --rpc-url http://localhost:8545
```which should return `1`.
You can also send a transaction to call the `store` function
```
cast send --private-key "store(uint256)" 5 --rpc-url http://localhost:8545
```where the private key needs to have some funds to pay for the transaction (for this you can use one of the miner accounts). Output should look like this
```
blockHash "0xd2f9afae4ef28c63ceccd7575c4370c17ead74448567ca651ec82a7051434e01"
blockNumber "0x5"
contractAddress null
cumulativeGasUsed "0x6746"
effectiveGasPrice "0xd1790ced"
gasUsed "0x6746"
logs []
logsBloom "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
root null
status "0x1"
transactionHash "0x0bc2448d1f7ee4be24bae1201e687d937d5f094af5e64f09ca0b279d62bf0b81"
transactionIndex "0x0"
type "0x2"
```After storing a number, you can retrieve it with
```
cast call "retrieve()(uint256)" --rpc-url http://localhost:8545
```
### CodeApart from EthClient calls, other modules can be called.
- RPC module handles RPC calls to the node.
- ABI module is a helper used to get the ABI of the desired contract, either calling to etherscan or locally.
- The Contract module uses the ABI module to generate elixir functions that invoke/call the said methods in the contract.
- The Account module defines a struct for accounts
- The Context module saves the current context, ie. contract ABI and address, and is updated as used. It is maintained with a Supervisor process.
- The RawTransaction module handles encoding of transactions for sending. (via RPC module)
- The Application module handles environment