-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 82d8c4f
Showing
48 changed files
with
9,264 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
Oops, something went wrong.