diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 66223e6a..69eb6009 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -2,3 +2,7 @@ * xref:access-control.adoc[Access Control] * xref:crypto.adoc[Cryptography] + +* xref:tokens.adoc[Tokens] +** xref:erc20.adoc[ERC-20] +** xref:erc721.adoc[ERC-721] diff --git a/docs/modules/ROOT/pages/erc20.adoc b/docs/modules/ROOT/pages/erc20.adoc new file mode 100644 index 00000000..2df693bf --- /dev/null +++ b/docs/modules/ROOT/pages/erc20.adoc @@ -0,0 +1,70 @@ += ERC-20 + +An ERC-20 token contract keeps track of xref:tokens.adoc#different-kinds-of-tokens[_fungible_ tokens]: any token is exactly equal to any other token; no token has a special right or behavior associated with them. +This makes ERC-20 tokens useful for things like a *medium of exchange currency*, *voting rights*, *staking*, and more. + +OpenZeppelin Contracts provide many ERC20-related contracts for Arbitrum Stylus. +On the https://docs.rs/openzeppelin_stylus/token/erc20/struct.Erc20.html[`API reference`] you'll find detailed information on their properties and usage. + +[[constructing-an-erc20-token-contract]] +== Constructing an ERC-20 Token Contract + +Using Contracts, we can easily create our own ERC-20 token contract, which will be used to track _Gold_ (GLD), an internal currency in a hypothetical game. + +Here's what our GLD token might look like. + +[source,rust] +---- +sol_storage! { + #[entrypoint] + struct GLDToken { + #[borrow] + Erc20 erc20; + #[borrow] + Erc20Metadata metadata; + } +} + +#[external] +#[inherit(Erc20, Erc20Metadata)] +impl GLDToken {} +---- + +Our contracts are often used via stylus-sdk https://docs.arbitrum.io/stylus/reference/rust-sdk-guide#inheritance-inherit-and-borrow[inheritance], and here we're reusing https://docs.rs/openzeppelin_stylus/token/erc20/struct.Erc20.html[`ERC20`] for both the basic standard implementation and with optional extensions. + +[[a-note-on-decimals]] +== A Note on `decimals` + +Often, you'll want to be able to divide your tokens into arbitrary amounts: say, if you own `5 GLD`, you may want to send `1.5 GLD` to a friend, and keep `3.5 GLD` to yourself. +Unfortunately, Solidity and the EVM do not support this behavior: only integer (whole) numbers can be used, which poses an issue. +You may send `1` or `2` tokens, but not `1.5`. + +To work around this, ERC20 provides a https://docs.rs/openzeppelin_stylus/token/erc20/extensions/metadata/trait.IErc20Metadata.html#tymethod.decimals[`decimals`] field, which is used to specify how many decimal places a token has. +To be able to transfer `1.5 GLD`, `decimals` must be at least `1`, since that number has a single decimal place. + +How can this be achieved? +It's actually very simple: a token contract can use larger integer values, so that a balance of `50` will represent `5 GLD`, a transfer of `15` will correspond to `1.5 GLD` being sent, and so on. + +It is important to understand that `decimals` is _only used for display purposes_. +All arithmetic inside the contract is still performed on integers, and it is the different user interfaces (wallets, exchanges, etc.) that must adjust the displayed values according to `decimals`. +The total token supply and balance of each account are not specified in `GLD`: you need to divide by `10 ** decimals` to get the actual `GLD` amount. + +You'll probably want to use a `decimals` value of `18`, just like Ether and most ERC-20 token contracts in use, unless you have an exceptional reason not to. +When minting tokens or transferring them around, you will be actually sending the number `GLD * (10 ** decimals)`. + +NOTE: By default, `ERC20` uses a value of `18` for `decimals`. +To use a different value, you will need to override the `decimals()` function in your contract. + +[source,rust] +---- +pub fn decimals(&self) -> u8 { + 16 +} +---- + +So if you want to send `5` tokens using a token contract with `18` decimals, the method to call will actually be: + +[source,rust] +---- +token.transfer(recipient, 5 * uint!(10_U256).pow(uint!(18_U256))); +---- diff --git a/docs/modules/ROOT/pages/tokens.adoc b/docs/modules/ROOT/pages/tokens.adoc new file mode 100644 index 00000000..87c2a03b --- /dev/null +++ b/docs/modules/ROOT/pages/tokens.adoc @@ -0,0 +1,29 @@ += Tokens + +Ah, the "token": blockchain's most powerful and most misunderstood tool. + +A token is a _representation of something in the blockchain_. This something can be money, time, services, shares in a company, a virtual pet, anything. By representing things as tokens, we can allow smart contracts to interact with them, exchange them, create or destroy them. + +[[but_first_coffee_a_primer_on_token_contracts]] +== But First, [strikethrough]#Coffee# a Primer on Token Contracts + +Much of the confusion surrounding tokens comes from two concepts getting mixed up: _token contracts_ and the actual _tokens_. + +A _token contract_ is simply an Ethereum smart contract. "Sending tokens" actually means "calling a method on a smart contract that someone wrote and deployed". At the end of the day, a token contract is not much more than a mapping of addresses to balances, plus some methods to add and subtract from those balances. + +It is these balances that represent the _tokens_ themselves. Someone "has tokens" when their balance in the token contract is non-zero. That's it! These balances could be considered money, experience points in a game, deeds of ownership, or voting rights, and each of these tokens would be stored in different token contracts. + +[[different-kinds-of-tokens]] +== Different Kinds of Tokens + +Note that there's a big difference between having two voting rights and two deeds of ownership: each vote is equal to all others, but houses usually are not! This is called https://en.wikipedia.org/wiki/Fungibility[fungibility]. _Fungible goods_ are equivalent and interchangeable, like Ether, fiat currencies, and voting rights. _Non-fungible_ goods are unique and distinct, like deeds of ownership, or collectibles. + +In a nutshell, when dealing with non-fungibles (like your house) you care about _which ones_ you have, while in fungible assets (like your bank account statement) what matters is _how much_ you have. + +== Standards + +Even though the concept of a token is simple, they have a variety of complexities in the implementation. Because everything in Ethereum is just a smart contract, and there are no rules about what smart contracts have to do, the community has developed a variety of *standards* (called EIPs or ERCs) for documenting how a contract can interoperate with other contracts. + +You've probably heard of the ERC-20 or ERC-721 token standards, and that's why you're here. Head to our specialized guides to learn more about these: + + * xref:erc20.adoc[ERC-20]: the most widespread token standard for fungible assets, albeit somewhat limited by its simplicity. \ No newline at end of file