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

ERC20 Permit Component #1140

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Added

- ERC20Permit component and preset
immrsd marked this conversation as resolved.
Show resolved Hide resolved

## 0.16.0 (2024-08-30)

### Added
Expand Down
92 changes: 92 additions & 0 deletions packages/presets/src/erc20_permit.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts for Cairo v0.16.0 (presets/erc20_permit.cairo)

/// # ERC20Permit Preset
///
/// The ERC20Permit preset integrates standard ERC20 token functionality with the ERC20Permit
/// extension, as defined by EIP-2612. This preset allows for token approvals via off-chain
/// signatures, thus enhancing transaction efficiency by reducing the need for on-chain approval
/// transactions.
immrsd marked this conversation as resolved.
Show resolved Hide resolved
///
/// This implementation features a fixed-supply model and the initial owner is specified in the
/// constructor.
///
/// The preset implements SNIP12Metadata with hardcoded values. These values are part of a
/// signature (following SNIP-12 standard) used for ERC20Permit functionality. It's crucial that the
/// SNIP12Metadata name remains unique to avoid confusion and potential security issues.
///
/// For more complex or custom contracts, use Wizard for Cairo
immrsd marked this conversation as resolved.
Show resolved Hide resolved
/// https://wizard.openzeppelin.com/cairo
#[starknet::contract]
pub mod ERC20Permit {
use openzeppelin_token::erc20::extensions::ERC20PermitComponent;
use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
use openzeppelin_utils::cryptography::nonces::NoncesComponent;
use openzeppelin_utils::cryptography::snip12::SNIP12Metadata;
use starknet::ContractAddress;

component!(path: ERC20Component, storage: erc20, event: ERC20Event);
component!(path: ERC20PermitComponent, storage: erc20_permit, event: ERC20PermitEvent);
component!(path: NoncesComponent, storage: nonces, event: NoncesEvent);

// ERC20Mixin
#[abi(embed_v0)]
impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;
impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;

// ERC20Permit
#[abi(embed_v0)]
impl ERC20PermitImpl = ERC20PermitComponent::ERC20PermitImpl<ContractState>;

// SNIP12Metadata
#[abi(embed_v0)]
impl SNIP12MetadataExternalImpl =
ERC20PermitComponent::SNIP12MetadataExternalImpl<ContractState>;

#[storage]
struct Storage {
#[substorage(v0)]
erc20: ERC20Component::Storage,
#[substorage(v0)]
erc20_permit: ERC20PermitComponent::Storage,
#[substorage(v0)]
nonces: NoncesComponent::Storage
}

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

/// Sets the token `name` and `symbol`.
/// Mints `fixed_supply` tokens to `recipient`.
#[constructor]
fn constructor(
ref self: ContractState,
name: ByteArray,
symbol: ByteArray,
fixed_supply: u256,
recipient: ContractAddress
) {
self.erc20.initializer(name, symbol);
self.erc20.mint(recipient, fixed_supply);
}

impl SNIP12MetadataImpl of SNIP12Metadata {
/// Returns token name to be used for SNIP-12 signature.
fn name() -> felt252 {
'My unique token name'
}

/// Returns token version to be used for SNIP-12 signature.
fn version() -> felt252 {
'v1'
}
}
}
2 changes: 2 additions & 0 deletions packages/presets/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod account;
pub mod erc1155;
pub mod erc20;
pub mod erc20_permit;
pub mod erc721;
pub mod eth_account;
pub mod interfaces;
Expand All @@ -11,6 +12,7 @@ pub mod universal_deployer;
pub use account::AccountUpgradeable;
pub use erc1155::ERC1155Upgradeable;
pub use erc20::ERC20Upgradeable;
pub use erc20_permit::ERC20Permit;
pub use erc721::ERC721Upgradeable;
pub use eth_account::EthAccountUpgradeable;
pub use universal_deployer::UniversalDeployer;
2 changes: 2 additions & 0 deletions packages/presets/src/tests.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ mod test_erc1155;
#[cfg(test)]
mod test_erc20;
#[cfg(test)]
mod test_erc20_permit;
#[cfg(test)]
mod test_erc721;
#[cfg(test)]
mod test_eth_account;
Expand Down
Loading