From 12f9a5daec5265d2c90e7050f165f205d29a2102 Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Wed, 17 Oct 2018 05:48:58 +0000 Subject: [PATCH] docs: remove basil and crafty demos The demos are outdated. For 2.0, they should probably be replaced with simpler examples. Fixes: #96 [CI skip] --- packages/docs/docs/docs/basil.md | 258 ----------------------- packages/docs/docs/docs/crafty.md | 198 ----------------- packages/docs/docs/docs/start.md | 2 - packages/docs/docs/website/sidebars.json | 6 +- 4 files changed, 1 insertion(+), 463 deletions(-) delete mode 100644 packages/docs/docs/docs/basil.md delete mode 100644 packages/docs/docs/docs/crafty.md diff --git a/packages/docs/docs/docs/basil.md b/packages/docs/docs/docs/basil.md deleted file mode 100644 index eff1e1c4c..000000000 --- a/packages/docs/docs/docs/basil.md +++ /dev/null @@ -1,258 +0,0 @@ ---- -id: basil -title: Zeppelin's Basil -sidebar_label: Basil ---- - -Here at the Zeppelin headquarters we have a basil plant. She is a good mascot, always green, always faithful. For reasons unknown, we found that she enjoys a lot being under a light that changes color; so of course we got her the best multicolor LED bulb we could find. - -![The Basil](https://pbs.twimg.com/media/DdL2qciX4AEMeoR.jpg "The basil") - -However, after a few days we started having conflicts. Who gets the honor to set the light color for our friendly plant? What if they choose their favorite color instead of the one that's best for the plant? For how long do they get to keep their chosen color? We also found that somebody kept resetting the color back to an ugly lime green every morning. We are ok with anarchy, but we want transparency, so we decided to control the light bulb through a contract on the Ethereum blockchain. - -## Creating an app with ZeppelinOS - -In this guide, we will build a simple dapp on top of ZeppelinOS. To see the end product, please visit: -* Source code: [zeppelinos/basil](https://github.com/zeppelinos/basil) -* App: [basil.zeppelin.solutions](https://basil.zeppelin.solutions) - -We will need to [install Node.js following the instructions from their website](https://nodejs.org/en/download/package-manager/). - -First, let's install the ZeppelinOS command line interface: - -```sh -npm install --global zos -``` - -Then, let's set up a directory for our project and initialize the npm package: - -```sh -mkdir basil -cd basil -npm init --yes -``` - -## The sample contract - -Next, let's take a look at the `Basil` contract we will use to control the light bulb: - -```sol -pragma solidity ^0.4.21; - -import "openzeppelin-zos/contracts/ownership/Ownable.sol"; - -/** - * @title Basil - */ -contract Basil is Ownable { - - // color - uint256 public r; - uint256 public g; - uint256 public b; - - // highest donation in wei - uint256 public highestDonation; - - event Withdrawal(address indexed wallet, uint256 value); - event NewDonation(address indexed donor, uint256 value, uint256 r, uint256 g, uint256 b); - - function donate(uint256 _r, uint256 _g, uint256 _b) public payable { - require(_r < 256); - require(_g < 256); - require(_b < 256); - require(msg.value > highestDonation); - - r = _r; - g = _g; - b = _b; - highestDonation = msg.value; - NewDonation( - msg.sender, msg.value, - r, g, b); - } - - function withdraw(address wallet) public onlyOwner { - require(this.balance > 0); - require(wallet != address(0)); - uint256 value = this.balance; - wallet.transfer(value); - Withdrawal(wallet, value); - } -} -``` - -The contract is super simple. If somebody wants to set the light color, they have to make a donation. If the donation is -higher than the previous one, it is accepted, the light color changes and an event is emitted. Of course, a withdraw -method allows the Zeppelin team to collect all donations, which are safely put away in the plant's own education fund. - -## Using ZeppelinOS - -Now, to get the niceties that ZeppelinOS provides, let's initialize our application with the version 0.0.1: - -```sh -zos init basil 0.0.1 -``` - -This will create a `zos.json` file where ZeppelinOS will keep track of the contracts of your application. - -Next, let's copy the sourcecode of `Basil` into `contracts/Basil.sol` and add it to the `zos` project: - -```sh -zos add Basil -``` - -To have your `zos.json` file always up-to-date, run `zos add` for every new contract you add to your project. -This command will also compile your contracts by default. - -By now, the json files looks like this: - -```json -{ - "name": "Basil", - "version": "0.0.1", - "contracts": { - "Basil": "Basil" - } -} -``` - -OpenZeppelin will use this file to track your project's contracts on chain, making them upgradeable and dynamically linkable to pre-deployed EVM packages, as well see soon. - -## Deploying our first version of Basil, locally - -Let's start a local ethereum network: - -```sh -ganache-cli --deterministic -``` - -This will print 10 accounts. Copy the address of the first one, and then back into the initial terminal, export it as the `OWNER` because it will be useful for us later: - -```sh -export OWNER=
-``` - -Then, to deploy our app: - -```sh -zos push --from $OWNER --network local -``` - -The first time you run this command for a specific network, a new -`zos..json` will be created. This file will reflect the status -of your project in that specific network, including contract logic and instance addresses, etc. - -## Contract logic and upgradeable instances - -Notice how the file `zos.local.json` lists a series of "contracts" and "proxies". The first are the logic contracts for a specific contract name, while the second are the actual contract instances that our users will interact with in the blockchain. - -A proxy is a wrapper for a contract's logic, that allows it to be updated, while maintaining its state. We need to create an upgradeable instance (proxy) for Basil. - -```sh -zos create Basil --from $OWNER --network local --init --args $OWNER -``` - -Take a look at `zos.local.json` again. You will see that we now have a proxy for Basil. This is the address to use in our app. - -## Upgrading the contract - -If we ever found a bug in Basil, we would need to upgrade our zos package, provide a new implementation for Basil with a fix and tell our proxy to upgrade to the new implementation. This would preserve all the previous donation history, while seamlessly patching the bug. - -Another common thing that happens when developing smart contracts for Ethereum is that new standards appear, all the new kids implement them in their contracts, and a very cool synergy between contracts starts to happen. Developers who have already deployed immutable contracts will miss all the fun. For example, it would be very nice to encourage donations to Basil by emitting a unique ERC721 token in exchange. Well, let's upgrade the contract with ZeppelinOS to do just that. - -We could modify `contracts/Basil.sol`. But now let's try something else. Let's make a new contract in `contracts/BasilERC721.sol`, that inherits from our initial version of Basil: - -```sol -pragma solidity ^0.4.21; - -import "./Basil.sol"; -import "openzeppelin-zos/contracts/token/ERC721/MintableERC721Token.sol"; -import "openzeppelin-zos/contracts/math/SafeMath.sol"; - -contract BasilERC721 is Basil { - using SafeMath for uint256; - - // ERC721 non-fungible tokens to be emitted on donations. - MintableERC721Token public token; - uint256 public numEmittedTokens; - - function setToken(MintableERC721Token _token) external onlyOwner { - require(_token != address(0)); - require(token == address(0)); - token = _token; - } - - function donate(uint256 _r, uint256 _g, uint256 _b) public payable { - super.donate(_r, _g, _b); - emitUniqueToken(tx.origin); - } - - function emitUniqueToken(address _tokenOwner) internal { - token.mint(_tokenOwner, numEmittedTokens); - numEmittedTokens = numEmittedTokens.add(1); - } -} -``` - -A few things to note: - * This new version extends from the previous one. This is a very handy pattern, because the proxy used in ZeppelinOS requires new versions to preserve the state variables. - * We can add new state variables and new functions. The only thing that we can't do on a contract upgrade is to remove state variables. - -Let's create a new version of our app, with the new contracts: - -```sh -zos bump 0.0.2 -``` - -Let's add this version to our ZeppelinOS application and push to the network again: - -```sh -truffle compile -zos add BasilERC721:Basil -zos push --from $OWNER --network local -``` - -This will print the address of the deployed Basil contract. Let's export this value to use it later: - -```sh -export BASIL_ADDRESS=
-``` - -Now, to update our proxy: - -```sh -zos update Basil --from $OWNER --network local -``` - -By now, Basil's proxy will use the new implementation, but it will revert on every donation because it's token is not set. We'll do that next. - -## Connecting to OpenZeppelin's EVM package - -So far, we've used ZeppelinOS to seamlessly upgrade our app's contracts. We will now use it to create a proxy for a pre-deployed ERC721 token implementation. - -The first thing we need to do, is tell our app to link to the `openzeppelin-zos` EVM package release: - -```sh -zos link openzeppelin-zos -zos push --from $OWNER --deploy-libs --network local -``` - -Notice the `--deploy-libs` option we've used. What this does is inject a version of the EVM package in our development network. Since we're working on a local blockchain, ZeppelinOS's contracts don't exist. This handy option solves that problem for us quite conveniently ^^ - -Now, to create a proxy for the token: - -```sh -zos create MintableERC721Token --from $OWNER --init --args \"$BASIL_ADDRESS\",\"BasilToken\",\"BSL\" --network local -``` - -This command will output the token's new proxy address. Let's use it in our new BasilERC721 version: - -```sh -export TOKEN_ADDRESS=
-echo "BasilERC721.at(\"$BASIL_ADDRESS\").setToken(\"$TOKEN_ADDRESS\", {from: \"$OWNER\"})" | npx truffle console --network local -``` - -That's it! Now you know how to use ZeppelinOS to develop upgradeable apps. Have a look at the scripts `deploy/deploy_with_cli_v1.sh` and `deploy/deploy_with_cli_v2.sh` to review what we've gone over in the guide. - -Stay tuned for more advanced tutorials! diff --git a/packages/docs/docs/docs/crafty.md b/packages/docs/docs/docs/crafty.md deleted file mode 100644 index 4e463ccbc..000000000 --- a/packages/docs/docs/docs/crafty.md +++ /dev/null @@ -1,198 +0,0 @@ ---- -id: crafty -title: Crafty ---- - -Have you ever wondered what may happen if you combined an Aragon token and fire? A fire-spewing eagle? Burnt chicken? What if Augur's oracles were augmented with Decentraland's tiles, would they start predicting the real estate market? Now, you no longer need to ponder at these vital questions: the Ethereum community will answer them for you! - -In [Crafty](https://crafty.zeppelin.solutions), users can create new ERC20 tokens, with a few added goodies (following [EIP-1046](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1046.md)): a picture, and a short description. This allows for each token to have that extra bit of personality that makes something unique. But that's not all: the only way to get these tokens is by crafting them, which requires ingredients (any ERC20!) to be spent. And since the craftable tokens themselves can also be used as ingredients, the posibilities are endless! Not only that, but we'll make all of our contracts upgradeable, to be able to change the code in the future. Wohoo! - -## Project setup - -This guide will show you the process of making the contracts in the Crafty game upgradeable by using ZeppelinOS, which we'll install globally to have it available on all our projects. - -```sh -npm install --global zos -``` - -See [here](setup.md) for more detailed setup info. - -All snippets here were extracted from the public [Crafty repository](https://github.com/zeppelinos/crafty). - -## Contracts - -Crafty works with only two contracts: -* [`Crafty`](https://github.com/zeppelinos/crafty/blob/master/contracts/Crafty.sol) itself, containing the game logic (how new recipes are added, how crafting takes place, etc.) plus some role-based access control ([RBAC](https://github.com/OpenZeppelin/openzeppelin-solidity/blob/zos-release/contracts/ownership/rbac/RBAC.sol), powered by [OpenZeppelin](https://openzeppelin.org/)), for admin tasks, such as deletion of tokens. -* The [`CraftableToken`](https://github.com/zeppelinos/crafty/blob/master/contracts/CraftableToken.sol)s, a simple extension of a mintable ERC20, which holds token creator data, a URI for metadata, and a list of required ingredients, along with the amounts of each. - -To better see how these two contracts interact, take a look at `Crafty`'s `craft` method, where a user provides the address of a `CraftableToken` to craft, and `Crafty` makes sure the required ingredients are consumed before minting it. - -``` -function craft(CraftableToken _craftable) public { - address player = msg.sender; - - uint256 totalSteps = _craftable.getTotalRecipeSteps(); - for (uint i = 0; i < totalSteps; ++i) { - ERC20 ingredient; - uint256 amountNeeded; - (ingredient, amountNeeded) = _craftable.getRecipeStep(i); - - ingredient.transferFrom(player, address(this), amountNeeded); - } - - _craftable.mint(player, 1); -} -``` - -## Developing with ZeppelinOS - -So, how would we go about integrating ZeppelinOS in such a project? The process is remarkably simple: we'll cover it step by step. But before we get started, let's initialize our project with ZeppelinOS: - -```sh -zos init Crafty -``` - -This will create a `zos.json` file, which will store how your project is structured in ZeppelinOS: you'll probably want to commit this file to your project's repository. - - -### Making Crafty upgradeable - -There are multiple reasons to upgrade `Crafty`'s game logic contract: bug-fixing, adding new functionalities, adjusting to newer developments and ecosystem changes, etc. Remember how `Crafty` uses RBAC (role-based access control)? An upgrade could easily add new roles, such as a `curator` role, which would be in charge of approving new tokens before they are added to the game, or highlighting featured creations to be displayed on the front page. These simple but useful extensions would not be possible without ZeppelinOS. - -`Crafty` is a great example of how easy it is to add upgradeability to your project. The only change that we need to make is a minor one: the constructor must be replaced with an `initialize` function. - -```js -import 'openzeppelin-zos/contracts/ownership/rbac/RBAC.sol'; -import 'zos-lib/contracts/migrations/Initializable.sol'; - -contract Crafty is RBAC, Initializable { - - // moved standard constructor logic to initializer function - // function Crafty() public { - // addRole(msg.sender, ROLE_ADMIN); - // } - - // Initializer for integration with ZeppelinOS - function initialize(address _initialAdmin) isInitializer public { - addRole(_initialAdmin, ROLE_ADMIN); - } - ... -} -``` - -The `isInitializer` modifier will make sure your `initialize` method is only called once in the whole lifetime of your contract. But you must remember to explicitly call it, since unlike constructors, `initialize` methods are not automatically called at contract creation. - -Also, note how we are using `openzeppelin-zos`, instead of the usual `openzeppelin-solidity`. This package's contracts have been adapted for ZeppelinOS compatibility, and should be the ones used when dealing with upgradeable contracts. - -Both `zos-lib` (for the `Initializable` contract) and `openzeppelin-zos` can be installed using [npm](https://www.npmjs.com/): - -```sh -npm install zos-lib openzeppelin-zos -``` - -With the `initialize` change in place, we're all set to start using upgradeable instances of the `Crafty` contract! First, we `add` it to the project's contracts, and then `push` the compiled bytecode of the current version to the blockchain. - -```sh -zos add Crafty -zos push --network ropsten --from $OWNER -``` - -The `from` parameter is important, since that address is the one that will be allowed to perform upgades to the contract. - -We can now `create` new upgradeable instances, all of which will use the same deployed bytecode, but are entirely independent otherwise. The `initialize` function can be called in this same step (with the `initialAdmin` argument), saving you the need to do it manually. - -```sh -zos create Crafty --init --args $OWNER --network ropsten -> 0x31C4B... -``` - -The returned value is the address of the newly created `Crafty` upgradeable instance, which is already initialized and can be safely used, with the peace of mind that it can later be upgraded at any point in time. - -### Making CraftableToken upgradeable - -This scenario is a bit more complex, since multiple ZeppelinOS contracts are being combined together, but it is nonetheless fairly easy to setup. Let's first recap what a `CraftableToken` is: - -1. It is detailed ERC20 token (i.e. has name and symbol) -1. It supports the [EIP-1046](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1046.md) extension of the ERC20 standard (i.e. we'll add a `tokenURI` parameter and variable) -1. It is mintable -1. It has additional storage of the token's ingredients, which require some validation - -Luckily for us, OpenZeppelin provides contracts that will implement 1 and 3 for us: `DetailedERC20` and `MintableToken`. 2 and 4 we'll have to cover on our own, but the process barely differs from what it would look like without ZeppelinOS. - -The EIP-1046 extension is straightforward: we'll inherit from OpenZeppelin's `DetailedERC20` and add the required variable to our contract. The only difference is, once again, that we need to define an `initialize` method instead of a constructor, and call our base contracts' `initialize` methods in it. - -``` -import 'openzeppelin-zos/contracts/token/ERC20/DetailedERC20.sol'; - -contract ExtendedERC20 is DetailedERC20 { - string public tokenURI; - - function initialize(address _sender, string _name, string _symbol, uint8 _decimals, string _tokenURI) isInitializer('ExtendedERC20', '0') public { - DetailedERC20.initialize(_sender, _name, _symbol, _decimals); - tokenURI = _tokenURI; - } -} -``` - -Since `DetailedERC20` already has the `isInitializer` modifier, we don't need to import it again. Note however, that we were required to supply two arguments: a contract name and a version id. - -The additional storage and validations will be implemented in the `CraftableToken` contract itself, which will feature multiple inheritance. Again, all that needs to be done is to call the `initialize` method of all base contracts. - -``` -import 'openzeppelin-zos/contracts/token/ERC20/MintableToken.sol'; -import './ExtendedERC20.sol'; - -contract CraftableToken is MintableToken, ExtendedERC20 { - function initialize(address _owner, string _name, string _symbol, string _tokenURI, ERC20[] _ingredients, uint256[] _ingredientAmounts) isInitializer('CraftableToken', '0') public { - MintableToken.initialize(_owner); - ExtendedERC20.initialize(_name, _symbol, 0, _tokenURI); - - // Do custom validation on _ingredients and _ingredientAmounts, and store them - ... - } - } - ... -} -``` - -`initialize`'s arguments can be passed in JSON to `create`, so arrays are not an issue: - -```sh -zos create CraftableToken --init --args "0x0cbd7..., \"Crafty Token\", \"CRFT\", \"https://path.to.metadata\", [0xd03ea..., 0x28a87...], [2, 4]" --network ropsten -> 0xaca94... -``` - -## Using our upgradeable contracts - -All that remains is having our contracts interact with each other. We'll want `Crafty` to store the different `CraftableToken`s so that they can be later listed by a player of the game: let's look at two different ways this could be done. - -First, we can have a player pass all of the arguments to a `Crafty` function, which will create a new `CraftableToken`, and add it to the list of tokens. Because we didn't create this instance with `zos create`, it is not upgradeable. Note how we need to call `initialize`, since `CraftableToken` doesn't have a constructor anymore. - -```js -function addCraftable(string _name, string _symbol, string _tokenURI, ERC20[] _ingredients, uint256[] _ingredientAmounts) public returns (CraftableToken) { - require(_ingredients.length == _ingredientAmounts.length); - require(_ingredients.length > 0); - - CraftableToken newCraftable = new CraftableToken(); - newCraftable.initialize(address(this), _name, _symbol, _tokenURI, _ingredients, _ingredientAmounts); - - craftables.push(newCraftable); - - emit CraftableAdded(newCraftable); - - return newCraftable; -} -``` - -What if we wanted to use the upgradeble instances we have `create`d with `zos`? We'll let admins add them into the game by simply providing the address of the contract. - -``` -function addPrecreatedCraftable(CraftableToken _craftable) onlyRole(ROLE_ADMIN) public { - craftables.push(_craftable); - emit CraftableAdded(_craftable); -} -``` - -A key point here is that both the upgradeable and non-upgradeable instances are treated in the same manner: `Crafty`'s `craft` method makes no distinction whatsoever when calling `CraftableToken` methods, since the interface is the same. A contract being upgradeable places no extra burden on its callers. - -This example shows how to add upgradeability and use EVM packages on a fairly complex smart contract app without too much work. Congratulations! diff --git a/packages/docs/docs/docs/start.md b/packages/docs/docs/docs/start.md index 47917bfe8..a6a6bfff1 100644 --- a/packages/docs/docs/docs/start.md +++ b/packages/docs/docs/docs/start.md @@ -23,8 +23,6 @@ If you would like to use the ZeppelinOS EVM packages in your app, If you are interested in deploying your own EVM packages for ZeppelinOS, see our [Developing a new EVM package](developing.md) guide. -Two demo apps based on ZeppelinOS are described in [Basil](basil.md) and [Crafty](crafty.md). - ## Security If you find a security issue, please contact us at security@zeppelinos.org. We diff --git a/packages/docs/docs/website/sidebars.json b/packages/docs/docs/website/sidebars.json index be8f9b515..844ef2929 100644 --- a/packages/docs/docs/website/sidebars.json +++ b/packages/docs/docs/website/sidebars.json @@ -11,10 +11,6 @@ "writing_contracts", "testing" ], - "DEMOS": [ - "basil", - "crafty" - ], "ADVANCED GUIDES": [ "erc20_onboarding", "upgradeability_governance" @@ -73,4 +69,4 @@ "upgradeability_UpgradeabilityProxyFactory" ] } -} \ No newline at end of file +}