Skip to content

Commit

Permalink
feat: add ERC20FlashMint extension (#407)
Browse files Browse the repository at this point in the history
<!--
Thank you for your interest in contributing to OpenZeppelin!

Consider opening an issue for discussion prior to submitting a PR. New
features will be merged faster if they were first discussed and designed
with the team.

Describe the changes introduced in this pull request. Include any
context necessary for understanding the PR's purpose.
-->

**NOTE: It is impossible to write any unit tests until it is possible to
mock `contract::address()` in tests (see
OpenZeppelin/stylus-test-helpers#5

<!-- Fill in with issue number -->
Resolves #355

#### PR Checklist

<!--
Before merging the pull request all of the following must be completed.
Feel free to submit a PR or Draft PR even if some items are pending.
Some of the items may not apply.
-->

- [x] Tests
- [x] Documentation
- [x] Changelog

---------

Co-authored-by: Nenad <[email protected]>
Co-authored-by: Nenad <[email protected]>
Co-authored-by: Daniel Bigos <[email protected]>
Co-authored-by: Alisander Qoshqosh <[email protected]>
  • Loading branch information
5 people authored Jan 7, 2025
1 parent 3ab0f31 commit 9d0a466
Show file tree
Hide file tree
Showing 26 changed files with 1,624 additions and 27 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:

# https://twitter.com/jonhoo/status/1571290371124260865
- name: Run unit tests
run: cargo nextest run --locked --features std --all-targets
run: cargo nextest run --locked --features std --all-targets -p openzeppelin-stylus -p openzeppelin-stylus-proc -p openzeppelin-crypto

# https://github.com/rust-lang/cargo/issues/6669
- name: Run doc tests
Expand Down Expand Up @@ -93,7 +93,7 @@ jobs:
run: cargo generate-lockfile

- name: Run unit tests
run: cargo nextest run --locked --features std --all-targets
run: cargo nextest run --locked --features std --all-targets -p openzeppelin-stylus -p openzeppelin-stylus-proc -p openzeppelin-crypto
coverage:
# Use llvm-cov to build and collect coverage and outputs in a format that
# is compatible with codecov.io.
Expand Down Expand Up @@ -141,7 +141,7 @@ jobs:
run: cargo generate-lockfile

- name: Cargo llvm-cov
run: cargo llvm-cov --locked --features std --lcov --output-path lcov.info
run: cargo llvm-cov --locked --features std --lcov --output-path lcov.info -p openzeppelin-stylus -p openzeppelin-stylus-proc -p openzeppelin-crypto

- name: Record Rust version
run: echo "RUST=$(rustc --version)" >> "$GITHUB_ENV"
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ docs/build/
**/.DS_Store

**/nitro-testnode

lcov.info

lcov.infos
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

-
- `Erc20FlashMint` extension. #407

### Changed

- Use `AddAssignUnchecked` and `SubAssignUnchecked` in `erc20::_update` calculations. #467
- Use `AddAssignUnchecked` and `SubAssignUnchecked` in `erc20::_update`. #467

### Changed (Breaking)

- `Nonce::use_nonce` now panics on exceeding `U256::MAX`. #467
- Add full support for reentrancy (changed `VestingWallet` signature for some functions). #407
- `Nonce::use_nonce` panics on exceeding `U256::MAX`. #467

### Fixed

Expand Down
15 changes: 14 additions & 1 deletion 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 @@ -7,6 +7,7 @@ members = [
"lib/e2e-proc",
"examples/erc20",
"examples/erc20-permit",
"examples/erc20-flash-mint",
"examples/erc721",
"examples/erc721-consecutive",
"examples/erc721-metadata",
Expand All @@ -31,6 +32,7 @@ default-members = [
"lib/e2e-proc",
"examples/erc20",
"examples/erc20-permit",
"examples/erc20-flash-mint",
"examples/erc721",
"examples/erc721-consecutive",
"examples/erc721-metadata",
Expand Down
1 change: 1 addition & 0 deletions contracts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ rand.workspace = true
# features, because this crate is meant to be used in a `no_std` environment.
# Currently, the std feature is only used for testing purposes.
std = []
reentrant = ["stylus-sdk/reentrant"]

[lib]
crate-type = ["lib"]
Expand Down
18 changes: 11 additions & 7 deletions contracts/src/finance/vesting_wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ pub trait IVestingWallet {
///
/// # Arguments
///
/// * `&self` - Read access to the contract's state.
/// * `&mut self` - Write access to the contract's state.
/// * `token` - Address of the releasable token.
///
/// # Errors
Expand All @@ -266,7 +266,8 @@ pub trait IVestingWallet {
/// If total allocation exceeds `U256::MAX`.
/// If scaled, total allocation (mid calculation) exceeds `U256::MAX`.
#[selector(name = "releasable")]
fn releasable_erc20(&self, token: Address) -> Result<U256, Self::Error>;
fn releasable_erc20(&mut self, token: Address)
-> Result<U256, Self::Error>;

/// Release the native tokens (Ether) that have already vested.
///
Expand Down Expand Up @@ -335,7 +336,7 @@ pub trait IVestingWallet {
///
/// # Arguments
///
/// * `&self` - Read access to the contract's state.
/// * `&mut self` - Write access to the contract's state.
/// * `token` - Address of the token being released.
/// * `timestamp` - Point in time for which to check the vested amount.
///
Expand All @@ -350,7 +351,7 @@ pub trait IVestingWallet {
/// If scaled, total allocation (mid calculation) exceeds `U256::MAX`.
#[selector(name = "vestedAmount")]
fn vested_amount_erc20(
&self,
&mut self,
token: Address,
timestamp: u64,
) -> Result<U256, Self::Error>;
Expand Down Expand Up @@ -410,7 +411,10 @@ impl IVestingWallet for VestingWallet {
}

#[selector(name = "releasable")]
fn releasable_erc20(&self, token: Address) -> Result<U256, Self::Error> {
fn releasable_erc20(
&mut self,
token: Address,
) -> Result<U256, Self::Error> {
let vested = self.vested_amount_erc20(token, block::timestamp())?;
// SAFETY: total vested amount is by definition greater than or equal to
// the released amount.
Expand Down Expand Up @@ -467,13 +471,13 @@ impl IVestingWallet for VestingWallet {

#[selector(name = "vestedAmount")]
fn vested_amount_erc20(
&self,
&mut self,
token: Address,
timestamp: u64,
) -> Result<U256, Self::Error> {
let erc20 = IErc20::new(token);
let balance = erc20
.balance_of(Call::new(), contract::address())
.balance_of(Call::new_in(self), contract::address())
.map_err(|_| InvalidToken { token })?;

let total_allocation = balance
Expand Down
2 changes: 1 addition & 1 deletion contracts/src/token/erc1155/extensions/uri_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ mod tests {
use stylus_sdk::prelude::storage;

use super::Erc1155UriStorage;
use crate::token::erc1155::{extensions::Erc1155MetadataUri, Erc1155};
use crate::token::erc1155::extensions::Erc1155MetadataUri;

fn random_token_id() -> U256 {
let num: u32 = rand::random();
Expand Down
Loading

0 comments on commit 9d0a466

Please sign in to comment.