Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
nuke-web3 authored Aug 31, 2023
0 parents commit 82d8c4f
Show file tree
Hide file tree
Showing 48 changed files with 9,264 additions and 0 deletions.
42 changes: 42 additions & 0 deletions .github/workflows/forge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: forge build

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]


env:
FOUNDRY_PROFILE: ci

jobs:
check:
strategy:
fail-fast: true

name: Foundry project
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

# TODO Might have to cd into the evm directory for forge commands to work.

- name: Run Forge build
run: |
forge --version
forge build --sizes
id: build

# Tests are not expected to work on `main` because it is starter code.
# - name: Run Forge tests
# run: |
# forge test -vvv
# id: test
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Solidity Compiler files
evm/cache/
evm/out/

# Ignores forge development broadcast logs
!evm/broadcast
evm/broadcast/*/31337/
evm/broadcast/**/dry-run/

# Cargo artifacts from ink contracts
**/target

# Some common ones
.vscode
log/*.log
tmp/**
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[submodule "evm/lib/forge-std"]
path = evm/lib/forge-std
url = https://github.com/foundry-rs/forge-std
# [submodule "evm/lib/foundry-vyper"]
# path = evm/lib/foundry-vyper
# url = https://github.com/JoshOrndorff/foundry-vyper
675 changes: 675 additions & 0 deletions LICENSE.md

Large diffs are not rendered by default.

60 changes: 60 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Contract Writing Workshop

In this activity, each student will be assigned to write one contract in one particular contracting language by the instructor.

💡 **The class, as a whole, will write a few copies of each contract in each language.**

## The Contracts

The contracts we've chosen are intended to give a reasonable sampling of typical problems encountered in smart contract design.
They are also chosen to show off the strengths and weaknesses between the various programming languages in which they are implemented.

Sometimes an idea fits really nicely with a particular language.
Other times it is hard to express an idea in a particular language.
That may be because the language is too primitive or because the idea is bad and the language is helping you avoid a mistake.
Not all contracts will be available to implement in all languages.

- Socialism DAO - An on-chain organization in which the members agree to live as socialists and split their resources each according to their need
- Roulette - A casino-style game of chance
- TicTacToe - An on-chain version of the classic multi-player children's game
- Resource Market - A way for private individuals to trade among themselves in the three resources that give them life
- Simple Dex - Basically a Balancer v1 pool with all weights equal

## The Languages

We've chosen three languages that are most popular overall and in the Polkadot/Substrate ecosystem in particular.
There is a folder for each language, and you should look at its dedicated readme for further language-specific instructions.

- [ink!](https://use.ink/) _([starter contracts](wasm/))_
- [Solidity](https://soliditylang.org/) _([starter contracts](evm/src/solidity/))_
- [Vyper](https://docs.vyperlang.org/en/stable/) _([starter contracts](evm/src/vyper/))_

## Working Together

You are encouraged to work together with your classmates to complete this task and learn as much about smart contracting as you can along the way.
There are a few different sorts of people you may be naturally inclined to work with.

Some students will have the **same contract** as you, but a different language to implement it in.
You may find it useful to talk about the design of the contract storage or transactions with these folks.

Some students will have the **same language** as you, but a different contract to implement
You may find it useful to talk about syntax, semantics, and language-specific tips and tricks with these folks.

One or two students may have both the same language and contract as you.
**You may work with these people as well, but please do not blindly share code.** This is an **ungraded** assignment, so try to learn as much as possible.

## Completing the Exercise

At minimum, ensure that your contract has a robust test suite, that you can deploy your contract to a local test environment, and that it functions as expected within the test environment.

Once you are satisfied that your contract works, if there is time remaining, you may explore more freely.

- Some contracts contain `// Enhancement` comments, look for these for some ideas as to other features you could implement
- Write the contract in a different language
- Write another contract in your language
- Design and write your own contract, consider ones that may make money from your friends (as preparation for tomorrow's activity)

## License

Licensed under the terms of the [GPL-3](./LICENSE.md) or later.

31 changes: 31 additions & 0 deletions evm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Ethereum Virtual Machine Contracts

This folder is dedicated to smart contracts that run on the EVM.

This folder is structured as a [foundry project](https://book.getfoundry.sh/).

## Source

We have both Solidity code (in the `src/solidity` directory), and Vyper code (in the `src/vyper` directory).

Currently the solidity code is more carefully documented, and has a working test suite.
For these reasons, Solidity is a first class language, and Vyper is not yet.

## Testing

Test coverage for each project can be found in the `test` directory which is also divided into `vyper` and `solidity` subdirectories.
For example, `test/solidity/Roulette.t.sol` contains the tests for the solidity implementation of the roulette project.

Foundry projects use the `forge` command to run tests.
To test all evm projects you can simply run `forge test`.
But to test a specific project, you can run a more focused command like `forge test --match-path evm/test/solidity/Roulette.t.sol`

For lots more testing hints, see `forge test --help`.

## Learning Resources

If you are doing this workshop as part of the PBA, your instructors have already given you a short course in programming the EVM.
Even so, you may find these additional learning resources useful:

- https://docs.soliditylang.org/en/v0.8.20/
- https://docs.vyperlang.org/en/stable/toctree.html
1 change: 1 addition & 0 deletions evm/lib/forge-std
Submodule forge-std added at e8a047
54 changes: 54 additions & 0 deletions evm/src/solidity/ResourceMarket.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.8.0;

/// There are three resources needed to survive: Water, Food, and Wood.
enum Resource {
Water,
Wood,
Food
}

/// Most individuals can only produce one or two of the resources, and therefore collaboration is necessary for survival.
/// Therefore we create a free market in which participants can contribute resources when they have them.
/// Later members can withdraw resources in proportion to their contributions.
/// You are not required to withdraw the same resources you contributed.
abstract contract ResourceMarket {

/// The amount of water currently available on the market
uint water = 0;

/// The amount of food currently available on the market
uint food = 0;

/// The amount of wood currently available on the market
uint wood = 0;

/// The credit that each previous contributor has in the market.
/// This is the maximum amount of resources that they can withdraw.
mapping(address => uint) credit;

/// Contribute some of your own private resources to the market.
/// Contributions are made one asset at a time.
function contribute(uint amount, Resource resource) public virtual;

/// Withdraw some resources from the market into your own private reserves.
function withdraw(uint amount, Resource resource) public virtual;

}

// Enhancement: The first iteration of this contract allow users to contribute
// by simplifying calling a function with an integer parameter. Presumably there is
// a security guard somewhere near the real-world marketplace confirming the deposits
// are actually made. But there are no on-chain assets underlying the resource market.
// Modify the code to interface with three real ERC20 tokens called: Water, Wood, and Food.

// Enhancement: The resource trading logic in this contract is useful for way more
// scenarios than our simple wood, food, water trade. Generalize the contract to
// work with up to 5 arbitrary ERC20 tokens.

// Enhancement: If we are trading real food, wood, and water, we have real-world incentives
// to deposit ou excess resources. Storage is hard IRL. Water evaporates, food spoils, and wood rots.
// And all the resources are subject to robbery. But if we are talking about virtual assets,
// there are no such risks. And depositing funds into the market comes with an opportunity cost.
// Design a reward system where there is a small fee on every withdrawal, and that fee is paid to
// liquidity providers.
94 changes: 94 additions & 0 deletions evm/src/solidity/Roulette.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.8.0;

/// The colors of the slots placed on the roulette wheel
enum Color {
Red,
Black,
Green
}

/// A Bet on a specific color coming up on the Roulette wheel
struct ColorBet {
Color color;
uint amount;
address beneficiary;
}

/// Models a casino style roulette table
/// https://en.wikipedia.org/wiki/Roulette
/// with these exact tiles
/// https://bfgblog-a.akamaihd.net/uploads/2013/11/2-1-Roulette-Table-Wheel-1024x463.png
contract Roulette {

/// All existing open color bets
ColorBet[] color_bets;

/// The address of the "house" that operates this table.
/// This is initialized to the address that deployed the contract.
address house;

constructor() {
house = msg.sender;
}

/// Funds were added to the table
event Funded(uint amount);

/// A Bet for a particular color was placed
event ColorBetPlaced(ColorBet bet);

/// A Bet for a particular color was won
event ColorBetWon(ColorBet bet);

/// A Bet for a particular color was lost
event ColorBetLost(ColorBet bet);

/// Add money to the house's funds.
/// This can only be called by the house account to help prevent users from
/// accidentally depositing funds that do not back any bet.
/// Because we have this explicit function, we do not include a fallback function.
function fund_table() external payable {
//TODO
}

/// Place a bet on a specific color
function place_color_bet(Color color) external payable {
//TODO
}

/// Helper function to determine the color of a roulette tile
function color_of(uint n) internal pure returns(Color) {
//TODO
}

/// Spin the wheel to determine the winning number.
/// Also calls settle_bets to kick off settlement of all bets.
function spin() external {

// Get the "random" result and convert it into a roulette table value.
// This is not _quite_ perfectly fair because 2^256 % 38 != 0.
// We could handle that if we want, but we won't yet.
uint r = uint(blockhash(block.number - 1)); //FIXME we could have an interface for getting randomness and one contract assignment could be to implement a better randomness.
uint winning_number = r % 38;

settle_bets(winning_number);
}

/// Helper function to settle all bets given a winning number
/// The payouts can be complex.
/// https://www.omnicalculator.com/statistics/roulette-payout
function settle_bets(uint winning_number) internal {
//TODO
}
}

// Enhancement: Allow all kinds of other bets like:
// * even / odd
// * one-spot
// * two-spot
// * four-spot
// * Column
// * etc

// Enhancement: read about randomness in the evm and try to find a good source of fair randomness.
Loading

0 comments on commit 82d8c4f

Please sign in to comment.