Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ERC20 preset #810

Merged
merged 17 commits into from
Nov 21, 2023
Merged
10 changes: 10 additions & 0 deletions docs/modules/ROOT/pages/erc20.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,13 @@ mod MyToken {
This contract expects a `decimals` argument in the constructor and uses an internal function to write the decimals to storage.
Note that the `decimals` state variable must be defined in the contract's storage because this variable does not exist in the component offered by OpenZeppelin Contracts for Cairo.
It's important to include a custom ERC20 metadata implementation and NOT use the Contracts for Cairo `ERC20MetadataImpl` in this specific case since the `decimals` method will always return `18`.

== Preset ERC20 contract
ericnordelo marked this conversation as resolved.
Show resolved Hide resolved

:erc20-preset: link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.0-beta.0/src/presets/erc20.cairo[ERC20 preset contract]

OpenZeppelin Contracts for Cairo offers an {erc20-preset}.
The contract provides basic functionality and uses a fixed-supply mechanism for token distribution.

This contract is ready to deploy without having to write any additional Cairo code.
It can be used as-is for quick prototyping and testing.
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`.
ericnordelo marked this conversation as resolved.
Show resolved Hide resolved
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
1 change: 1 addition & 0 deletions src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod access;
mod account;
mod introspection;
mod presets;
mod security;
#[cfg(test)]
mod tests;
Expand Down
2 changes: 2 additions & 0 deletions src/presets.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod erc20;
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 Contract
///
/// The ERC20 preset 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.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod access;
mod account;
mod introspection;
mod mocks;
mod presets;
mod security;
mod token;
mod upgrades;
Expand Down
1 change: 1 addition & 0 deletions src/tests/presets.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod test_erc20;
Loading