Skip to content

Commit

Permalink
Add ERC20 preset (#810)
Browse files Browse the repository at this point in the history
* add erc20 preset

* add tests

* fix formatting

* change preset name

* tidy up tests

* normalize assert msgs

* simplify ZERO, add other transfer tests

* add other transfer tests

* add erc20 preset section

* fix preset sentence

* change initial_supply to fixed_supply

* add code comments

* move preset to API

* Apply suggestions from code review

Co-authored-by: Martín Triay <[email protected]>

* fix preset section sentence

* normalize comments

---------

Co-authored-by: Martín Triay <[email protected]>
  • Loading branch information
andrew-fleming and martriay authored Nov 21, 2023
1 parent f3e2a5f commit 7a7be63
Show file tree
Hide file tree
Showing 7 changed files with 661 additions and 46 deletions.
44 changes: 42 additions & 2 deletions docs/modules/ROOT/pages/api/erc20.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ use openzeppelin::token::erc20::ERC20Component;
```
ERC20 component extending <<IERC20,IERC20>> and <<IERC20Metadata,IERC20Metadata>>.

[.contract-index]
[.contract-index#ERC20Component-Embeddable-Impls]
.Embeddable implementations
--
.ERC20Impl
Expand All @@ -189,7 +189,7 @@ ERC20 component extending <<IERC20,IERC20>> and <<IERC20Metadata,IERC20Metadata>
* xref:#ERC20Component-decrease_allowance[`++decrease_allowance(self, spender, subtracted_value)++`]
--

[.contract-index]
[.contract-index#ERC20Component-Embeddable-Impls-camelCase]
.Embeddable implementations (camelCase)
--
.ERC20CamelOnlyImpl
Expand Down Expand Up @@ -471,3 +471,43 @@ See <<IERC20-Transfer,IERC20::Transfer>>.
==== `[.contract-item-name]#++Approval++#++(owner: ContractAddress, spender: ContractAddress, value: u256)++` [.item-kind]#event#

See <<IERC20-Approval,IERC20::Approval>>.

== Presets

[.contract]
[[ERC20]]
=== `++ERC20++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.0/src/presets/erc20.cairo[{github-icon},role=heading-link]

```javascript
use openzeppelin::presets::ERC20;
```

Basic ERC20 contract leveraging xref:#ERC20Component[ERC20Component] with a fixed-supply mechanism for token distribution.

[.contract-index]
.Constructor
--
* xref:#ERC20-constructor[`++constructor(self, name, symbol, fixed_supply, recipient)++`]
--

[.contract-index]
.Embedded Implementations
--
.ERC20Component

* xref:#ERC20Component-Embeddable-Impls[`++ERC20Impl++`]
* xref:#ERC20Component-Embeddable-Impls[`++ERC20MetadataImpl++`]
* xref:#ERC20Component-Embeddable-Impls[`++SafeAllowanceImpl++`]
* xref:#ERC20Component-Embeddable-Impls-camelCase[`++ERC20CamelOnlyImpl++`]
* xref:#ERC20Component-Embeddable-Impls-camelCase[`++SafeAllowanceCamelImpl++`]
--

[#ERC20-constructor-section]
==== Constructor

[.contract-item]
[[ERC20-constructor]]
==== `[.contract-item-name]#++constructor++#++(ref self: ContractState, name: felt252, symbol: felt252, fixed_supply: u256, recipient: ContractAddress)++` [.item-kind]#constructor#

Sets the `name` and `symbol`.
Mints `fixed_supply` tokens to `recipient`.
6 changes: 3 additions & 3 deletions docs/modules/ROOT/pages/guides/erc20-supply.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,20 @@ mod MyToken {
#[constructor]
fn constructor(
ref self: ContractState,
initial_supply: u256,
fixed_supply: u256,
recipient: ContractAddress
) {
let name = 'MyToken';
let symbol = 'MTK';
self.erc20.initializer(name, symbol);
self.erc20._mint(recipient, initial_supply);
self.erc20._mint(recipient, fixed_supply);
}
}
----

In the constructor, we're first calling the ERC20 initializer to set the token name and symbol.
Next, we're calling the internal `_mint` function which creates `initial_supply` of tokens and allocates them to `recipient`.
Next, we're calling the internal `_mint` function which creates `fixed_supply` of tokens and allocates them to `recipient`.
Since the internal `_mint` is not exposed in our contract, it will not be possible to create any more tokens.
In other words, we've implemented a fixed token supply!

Expand Down
2 changes: 2 additions & 0 deletions src/presets.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod account;
mod erc20;

use account::Account;
use erc20::ERC20;
55 changes: 55 additions & 0 deletions src/presets/erc20.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts for Cairo v0.8.0-beta.0 (presets/erc20.cairo)

/// # ERC20 Preset
///
/// The ERC20 contract offers basic functionality and provides a
/// fixed-supply mechanism for token distribution. The fixed supply is
/// set in the constructor.
#[starknet::contract]
mod ERC20 {
use openzeppelin::token::erc20::ERC20Component;
use starknet::ContractAddress;

component!(path: ERC20Component, storage: erc20, event: ERC20Event);

#[abi(embed_v0)]
impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
#[abi(embed_v0)]
impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl<ContractState>;
#[abi(embed_v0)]
impl SafeAllowanceImpl = ERC20Component::SafeAllowanceImpl<ContractState>;
#[abi(embed_v0)]
impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl<ContractState>;
#[abi(embed_v0)]
impl SafeAllowanceCamelImpl =
ERC20Component::SafeAllowanceCamelImpl<ContractState>;
impl InternalImpl = ERC20Component::InternalImpl<ContractState>;

#[storage]
struct Storage {
#[substorage(v0)]
erc20: ERC20Component::Storage
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
ERC20Event: ERC20Component::Event
}

/// Sets the token `name` and `symbol`.
/// Mints `fixed_supply` tokens to `recipient`.
#[constructor]
fn constructor(
ref self: ContractState,
name: felt252,
symbol: felt252,
fixed_supply: u256,
recipient: ContractAddress
) {
self.erc20.initializer(name, symbol);
self.erc20._mint(recipient, fixed_supply);
}
}
1 change: 1 addition & 0 deletions src/tests/presets.cairo
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
mod test_account;
mod test_erc20;
Loading

0 comments on commit 7a7be63

Please sign in to comment.