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

feat: Erc20Wrapper extension #498

Draft
wants to merge 45 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
1944622
chore: wrapper approch
Ifechukwudaniel Jan 16, 2025
0cca59f
chore: code fmt
Ifechukwudaniel Jan 16, 2025
3bab6ac
chore: comments
Ifechukwudaniel Jan 16, 2025
038020b
chore: erc20 wrapper token
Ifechukwudaniel Jan 16, 2025
7587d34
chore: code fmt
Ifechukwudaniel Jan 16, 2025
961353e
chore: wrapper example
Ifechukwudaniel Jan 16, 2025
a347f69
chore: erc20 wrapper
Ifechukwudaniel Jan 25, 2025
9c66630
chore: removed variable
Ifechukwudaniel Jan 25, 2025
bd69a58
chore: wrapper and example
Ifechukwudaniel Jan 26, 2025
1bedc16
chore: erc20 wrapper example
Ifechukwudaniel Jan 26, 2025
9d5419c
cargo fmt
Ifechukwudaniel Jan 26, 2025
2d6a02f
chore: fixed constructor test
Ifechukwudaniel Jan 27, 2025
398da73
chore: wrapper
Ifechukwudaniel Jan 27, 2025
3405bf2
chore: fomrmat
Ifechukwudaniel Jan 27, 2025
dfc1e00
chore: CHANGELOG
Ifechukwudaniel Jan 27, 2025
4274d2b
chore:docs
Ifechukwudaniel Jan 27, 2025
fd1de52
chore: removed docs
Ifechukwudaniel Jan 27, 2025
fb6a894
chore: erc20 wrappers docs
Ifechukwudaniel Jan 27, 2025
102611b
chore: fix underlying state
Ifechukwudaniel Jan 27, 2025
1f450b2
chore: fixed clippy error
Ifechukwudaniel Jan 27, 2025
fae5882
chore: fixed clippy warnings
Ifechukwudaniel Jan 27, 2025
f8d684a
docs
Ifechukwudaniel Jan 28, 2025
d13ad47
docs: added missing docs
Ifechukwudaniel Jan 28, 2025
ab401e2
chore: format
Ifechukwudaniel Jan 28, 2025
4070411
docs: ivalid to invalid
Ifechukwudaniel Jan 28, 2025
4ac2b5c
test: underlying test works
Ifechukwudaniel Jan 28, 2025
104c45a
test: test fixes
Ifechukwudaniel Jan 28, 2025
b6e1d6e
Merge branch 'main' into ERC20Wrapper
Ifechukwudaniel Jan 30, 2025
1b15a10
Merge branch 'main' into ERC20Wrapper
Ifechukwudaniel Jan 31, 2025
1114ccf
Merge branch 'main' into ERC20Wrapper
Ifechukwudaniel Feb 3, 2025
2a1cd43
unit test
Ifechukwudaniel Feb 4, 2025
c22a404
chore: erc20 wrapper
Ifechukwudaniel Feb 4, 2025
0124a8d
Merge branch 'main' into ERC20Wrapper
Ifechukwudaniel Feb 4, 2025
d680703
chore: function name fixes
Ifechukwudaniel Feb 4, 2025
9781c4e
Update contracts/src/token/erc20/extensions/mod.rs
Ifechukwudaniel Feb 5, 2025
a99faa4
Update contracts/src/token/erc20/extensions/wrapper.rs
Ifechukwudaniel Feb 5, 2025
afc75a3
Update contracts/src/token/erc20/extensions/wrapper.rs
Ifechukwudaniel Feb 5, 2025
cd0259a
Update contracts/src/token/erc20/extensions/wrapper.rs
Ifechukwudaniel Feb 5, 2025
293b12f
Merge branch 'main' into ERC20Wrapper
Ifechukwudaniel Feb 5, 2025
2535fef
chore: test fixes
Ifechukwudaniel Feb 5, 2025
0b92aab
chore: fixes
Ifechukwudaniel Feb 5, 2025
7a31409
chore: fmt
Ifechukwudaniel Feb 5, 2025
bc8aa8f
Update contracts/src/token/erc20/extensions/wrapper.rs
Ifechukwudaniel Feb 5, 2025
c9a1711
Update contracts/src/token/erc20/extensions/wrapper.rs
Ifechukwudaniel Feb 5, 2025
6fd4866
Update contracts/src/token/erc20/extensions/wrapper.rs
Ifechukwudaniel Feb 5, 2025
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Implement `mul_div` for `U256`. #465
- Implement `AddAssignChecked` for `StorageUint`. #474
- `Erc20FlashMint` extension. #407
- `Erc20Wrapper` "Token Wrapping contract". #498
Ifechukwudaniel marked this conversation as resolved.
Show resolved Hide resolved

### Changed

Expand Down
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ members = [
"examples/erc20",
"examples/erc20-permit",
"examples/erc20-flash-mint",
"examples/erc20-wrapper",
"examples/erc721",
"examples/erc721-consecutive",
"examples/erc721-metadata",
Expand Down Expand Up @@ -35,6 +36,7 @@ default-members = [
"examples/erc20",
"examples/erc20-permit",
"examples/erc20-flash-mint",
"examples/erc20-wrapper",
"examples/erc721",
"examples/erc721-consecutive",
"examples/erc721-metadata",
Expand Down
2 changes: 2 additions & 0 deletions contracts/src/token/erc20/extensions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ pub mod erc4626;
pub mod flash_mint;
pub mod metadata;
pub mod permit;
pub mod wrapper;

pub use burnable::IErc20Burnable;
pub use capped::Capped;
pub use erc4626::{Erc4626, IErc4626};
pub use flash_mint::{Erc20FlashMint, IErc3156FlashLender};
pub use metadata::{Erc20Metadata, IErc20Metadata};
pub use permit::Erc20Permit;
pub use wrapper::{Erc20Wrapper, IErc20Wrapper};
254 changes: 254 additions & 0 deletions contracts/src/token/erc20/extensions/wrapper.rs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please apply this #511 Rust docs layout in this contract.

Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
//! Extension of the ERC-20 token contract to support token wrapping.
//!
//! Users can deposit and withdraw "underlying tokens" and receive a matching
//! number of "wrapped tokens". This is useful in conjunction with other
//! modules.
//!
//! WARNING: Any mechanism in which the underlying token changes the {balanceOf}
Copy link
Collaborator

@bidzyyys bidzyyys Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjust the docs to the current implementation. We do not have balanceOf function.

//! of an account without an explicit transfer may desynchronize this contract's
//! supply and its underlying balance. Please exercise caution when wrapping
//! tokens that may undercollateralize the wrapper (i.e. wrapper's total supply
//! is higher than its underlying balance). See {_recover} for recovering value
//! accrued to the wrapper.

use alloy_primitives::{Address, U256};
use alloy_sol_macro::sol;
use stylus_sdk::{
call::Call,
contract, msg,
prelude::storage,
storage::{StorageAddress, TopLevelStorage},
stylus_proc::SolidityError,
};

use crate::token::erc20::{
self,
utils::{safe_erc20, IErc20 as IErc20Solidity, ISafeErc20, SafeErc20},
Erc20, IErc20,

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / nightly / coverage

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / stable / clippy

[clippy] reported by reviewdog 🐶 warning: unused import: `IErc20` --> contracts/src/token/erc20/extensions/wrapper.rs:27:12 | 27 | Erc20, IErc20, | ^^^^^^ | = note: `#[warn(unused_imports)]` on by default Raw Output: contracts/src/token/erc20/extensions/wrapper.rs:27:12:w:warning: unused import: `IErc20` --> contracts/src/token/erc20/extensions/wrapper.rs:27:12 | 27 | Erc20, IErc20, | ^^^^^^ | = note: `#[warn(unused_imports)]` on by default __END__

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / Gas usage report

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / Gas usage report

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / tests

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / tests

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / wasm32-unknown-unknown

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / Check WASM binary

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / macos-latest / stable

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / nightly / doc

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / beta

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / beta

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused import: `IErc20`

Check warning on line 27 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / beta / clippy

[clippy] reported by reviewdog 🐶 warning: unused import: `IErc20` --> contracts/src/token/erc20/extensions/wrapper.rs:27:12 | 27 | Erc20, IErc20, | ^^^^^^ | = note: `#[warn(unused_imports)]` on by default Raw Output: contracts/src/token/erc20/extensions/wrapper.rs:27:12:w:warning: unused import: `IErc20` --> contracts/src/token/erc20/extensions/wrapper.rs:27:12 | 27 | Erc20, IErc20, | ^^^^^^ | = note: `#[warn(unused_imports)]` on by default __END__
};

sol! {
Ifechukwudaniel marked this conversation as resolved.
Show resolved Hide resolved
/// Indicates that he address is not a valid ERC-20 token.
///
/// * `address` - Address of the invalid underling ERC-20 token.
#[derive(Debug)]
#[allow(missing_docs)]
error ERC20InvalidUnderlying(address token);

/// Indicates that the address is not an Invalid Sender address.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe there is sth wrong with this docs...

///
/// * `sender` - Address is an invalid sender.
#[derive(Debug)]
#[allow(missing_docs)]
error ERC20InvalidSender(address sender);

/// Indicates that The address is not a valid Invalid Asset.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe there is sth wrong with this docs...

///
/// * `asset` - Address of the invalid address of the token.
#[derive(Debug)]
#[allow(missing_docs)]
error InvalidAsset(address asset);

/// Indicates thata the address is not an invalid receiver addresss.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe there is sth wrong with this docs...

///
/// * `receiver` - Address of the invalid receiver.
#[derive(Debug)]
#[allow(missing_docs)]
error ERC20InvalidReceiver(address receiver);

}

/// An [`Erc20Wrapper`] error.
#[derive(SolidityError, Debug)]
pub enum Error {
/// Error type from [`SafeErc20`] contract [`safe_erc20::Error`].
SafeErc20(safe_erc20::Error),

/// The Sender Address is not valid.
InvalidSender(ERC20InvalidSender),

/// The Reciver Address is not valid.
InvalidReceiver(ERC20InvalidReceiver),

/// The underlying token couldn't be wrapped.
InvalidUnderlying(ERC20InvalidUnderlying),

/// The address is not a valid ERC-20 token.
InvalidAsset(InvalidAsset),

/// Error type from [`Erc20`] contract [`erc20::Error`].
Erc20(erc20::Error),
}
/// State of an [`Erc20Wrapper`] token.
#[storage]
pub struct Erc20Wrapper {
/// Token Address of the underline token
#[allow(clippy::used_underscore_binding)]
pub(crate) underlying_address: StorageAddress,

/// [`SafeErc20`] contract
safe_erc20: SafeErc20,
}

/// ERC-20 Wrapper Standard Interface
pub trait IErc20Wrapper {
/// The error type associated to the` trait implementation.

Check warning on line 95 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / stable / clippy

[clippy] reported by reviewdog 🐶 warning: backticks are unbalanced --> contracts/src/token/erc20/extensions/wrapper.rs:95:9 | 95 | /// The error type associated to the` trait implementation. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: a backtick may be missing a pair = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown = note: `-W clippy::doc-markdown` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::doc_markdown)]` Raw Output: contracts/src/token/erc20/extensions/wrapper.rs:95:9:w:warning: backticks are unbalanced --> contracts/src/token/erc20/extensions/wrapper.rs:95:9 | 95 | /// The error type associated to the` trait implementation. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: a backtick may be missing a pair = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown = note: `-W clippy::doc-markdown` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::doc_markdown)]` __END__

Check warning on line 95 in contracts/src/token/erc20/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / beta / clippy

[clippy] reported by reviewdog 🐶 warning: backticks are unbalanced --> contracts/src/token/erc20/extensions/wrapper.rs:95:9 | 95 | /// The error type associated to the` trait implementation. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: a backtick may be missing a pair = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown = note: `-W clippy::doc-markdown` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::doc_markdown)]` Raw Output: contracts/src/token/erc20/extensions/wrapper.rs:95:9:w:warning: backticks are unbalanced --> contracts/src/token/erc20/extensions/wrapper.rs:95:9 | 95 | /// The error type associated to the` trait implementation. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: a backtick may be missing a pair = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown = note: `-W clippy::doc-markdown` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::doc_markdown)]` __END__
type Error: Into<alloc::vec::Vec<u8>>;

/// Returns the address of the underlying token that is been wrapped.
fn underlying(&self) -> Address;

/// Allow a user to deposit underlying tokens and mint the corresponding
/// number of wrapped token
///
/// Arguments:
///
/// * `&mut self` - Write access to the contract's state.
/// * `account` - The account to deposit tokens to.
/// * `value` - The amount of tokens to deposit.
///
/// # Errors
///
/// * If the sender address is `contract:address()` or invalid,
/// [`Error::InvalidSender`] is returned.
/// * If the receiver address is `contract:address()` or invalid,
/// [`Error::InvalidReceiver`] is returned.
fn deposit_for(
&mut self,
account: Address,
value: U256,
erc20: &mut Erc20,
) -> Result<bool, Self::Error>;

/// Allow a user to burn a number of wrapped tokens and withdraw the
/// corresponding number of underlying tokens.
///
/// Arguments:
///
/// * `&mut self` - Write access to the contract's state.
/// * `account` - The account to withdraw tokens to.
/// * `value` - The amount of tokens to withdraw.
/// * `erc20` - A mutable reference to the Erc20 contract.
///
/// # Errors
///
/// * If the receiver address is `contract:address()` or invalid,
/// [`Error::InvalidReceiver`] is returned.
fn withdraw_to(
Ifechukwudaniel marked this conversation as resolved.
Show resolved Hide resolved
&mut self,
account: Address,
value: U256,
erc20: &mut Erc20,
) -> Result<bool, Self::Error>;
}

/// NOTE: Implementation of [`TopLevelStorage`] to be able use `&mut self` when
/// calling other contracts and not `&mut (impl TopLevelStorage +
/// BorrowMut<Self>)`. Should be fixed in the future by the Stylus team.
unsafe impl TopLevelStorage for Erc20Wrapper {}

impl IErc20Wrapper for Erc20Wrapper {
type Error = Error;

fn underlying(&self) -> Address {
self.underlying_address.get()
}

fn deposit_for(
&mut self,
account: Address,
value: U256,
erc20: &mut Erc20,
) -> Result<bool, Error> {
let sender = msg::sender();

if sender == contract::address() {
return Err(Error::InvalidReceiver(ERC20InvalidReceiver {
receiver: account,
}));
}

if account == contract::address() {
return Err(Error::InvalidSender(ERC20InvalidSender {
sender: contract::address(),
}));
}

self.safe_erc20.safe_transfer_from(
self.underlying(),
sender,
contract::address(),
value,
)?;
erc20._mint(account, value)?;
Ok(true)
}

fn withdraw_to(
&mut self,
account: Address,
value: U256,
erc20: &mut Erc20,
) -> Result<bool, Error> {
if account == contract::address() {
return Err(Error::InvalidReceiver(ERC20InvalidReceiver {
receiver: account,
}));
}
erc20._burn(account, value)?;
self.safe_erc20.safe_transfer(self.underlying(), account, value)?;
Ok(true)
}
}

impl Erc20Wrapper {
/// Mints wrapped tokens to cover any underlying tokens that might have been
/// mistakenly transferred or acquired through rebasing mechanisms.
///
/// This is an internal function that can be exposed with access control if
/// required.
///
/// Arguments:
///
/// * `&mut self` - Write access to the contract's state.
/// * `account` - The account to mint tokens to.
/// * `erc20` - A mutable reference to the Erc20 contract.
///
/// # Errors
///
/// If the external call for balance of fails , then the error
/// [`Error::InvalidAsset`] is returned.
pub fn _recover(
Ifechukwudaniel marked this conversation as resolved.
Show resolved Hide resolved
&mut self,
account: Address,
erc20: &mut Erc20,
) -> Result<U256, Error> {
let underline_token = IErc20Solidity::new(self.underlying());
let value = underline_token
.balance_of(Call::new_in(self), contract::address())
.map_err(|_| InvalidAsset { asset: contract::address() })?;
erc20._mint(account, value)?;
Ok(U256::from(value))
}
}

// TODO: Add missing tests once `motsu` supports calling external contracts.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have motsu version that support calling external contracts tomorrow :)
It is already merged into main branch of mostu. You can implement these test cases.

#[cfg(all(test, feature = "std"))]
mod tests {
use alloy_primitives::address;
use stylus_sdk::prelude::storage;

use super::{Erc20Wrapper, IErc20Wrapper};

#[storage]
struct Erc20WrapperTestExample {
wrapper: Erc20Wrapper,
}

#[motsu::test]
fn underlying_works(contract: Erc20WrapperTestExample) {
let asset = address!("DeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF");
contract.wrapper.underlying_address.set(asset);
assert_eq!(contract.wrapper.underlying(), asset);
}
}
57 changes: 57 additions & 0 deletions docs/modules/ROOT/pages/erc20-wrapper.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
= ERC-20 Wrapper

Extension of the ERC-20 token contract to support token wrapping.

Users can deposit and withdraw "underlying tokens" and receive a matching number of "wrapped tokens".
This is useful in conjunction with other modules.


[[usage]]
== Usage

In order to make your ERC20 `wrapped token`:

[source,rust]
----
use alloy_primitives::{Address, U256};
use openzeppelin_stylus::token::erc20::{
extensions::{Erc20Metadata, Erc20Wrapper, IERC20Wrapper},
Erc20,
};
use stylus_sdk::prelude::{entrypoint, public, storage};

#[entrypoint]
#[storage]
struct Erc20WrapperExample {
#[borrow]
pub erc20: Erc20,
#[borrow]
pub metadata: Erc20Metadata,
#[borrow]
pub wrapper: Erc20Wrapper,
}

#[public]
#[inherit(Erc20, Erc20Metadata)]
impl Erc20WrapperExample {
fn underlying(&self) -> Address {
self.wrapper.underlying()
}

fn deposit_to(
&mut self,
account: Address,
value: U256,
) -> Result<bool, Vec<u8>> {
Ok(self.wrapper.deposit_to(account, value, &mut self.erc20)?)
}

fn withdraw_to(
&mut self,
account: Address,
value: U256,
) -> Result<bool, Vec<u8>> {
Ok(self.wrapper.withdraw_to(account, value, &mut self.erc20)?)
}
}
----
2 changes: 2 additions & 0 deletions docs/modules/ROOT/pages/erc20.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,5 @@ Additionally, there are multiple custom extensions, including:
* xref:erc4626.adoc[ERC-4626]: tokenized vault that manages shares (represented as ERC-20) that are backed by assets (another ERC-20).

* xref:erc20-flash-mint.adoc[ERC-20 Flash-Mint]: token level support for flash loans through the minting and burning of ephemeral tokens (standardized as https://eips.ethereum.org/EIPS/eip-3156[`EIP-3156`]).

* xref:erc20-wrapper.adoc[ERC-20 Wrapper]: Extension of the ERC-20 token contract to support token wrapping .
Loading
Loading