Skip to content

ERC20 flash mint extension#1608

Merged
ericnordelo merged 11 commits intomainfrom
feat/erc20-flash-mint-#1577
Mar 31, 2026
Merged

ERC20 flash mint extension#1608
ericnordelo merged 11 commits intomainfrom
feat/erc20-flash-mint-#1577

Conversation

@ericnordelo
Copy link
Copy Markdown
Member

@ericnordelo ericnordelo commented Dec 9, 2025

Fixes #1577

PR Checklist

  • Tests
  • Documentation
  • Added entry to CHANGELOG.md
  • Tried the feature on a public network

Summary by CodeRabbit

Release Notes

  • New Features

    • Added ERC-3156 standard flash loan interfaces for single-transaction token loans.
    • Introduced ERC20 Flash Mint component enabling configurable flash loan functionality with customizable fees, loan caps, and fee recipients.
    • Added flash borrower interface for receiving and handling flash loans.
  • Tests

    • Added comprehensive test coverage for flash loan execution, fee handling, and receiver validation scenarios.

@ericnordelo ericnordelo changed the title EEC20 flash mint extension ERC20 flash mint extension Dec 9, 2025
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Dec 9, 2025

🧪 Cairo Contract Size Benchmark Diff

BYTECODE SIZE (felts) (limit: 81,920 felts)

Contract Old New Δ Note
ERC20FlashMintConfiguredMock 7570 +7570 ✅ NEW
ERC20FlashMintMock 7003 +7003 ✅ NEW
ERC3156FlashBorrowerMock 1014 +1014 ✅ NEW

SIERRA CONTRACT CLASS SIZE (bytes) (limit: 4,089,446 bytes)

Contract Old New Δ Note
ERC20FlashMintConfiguredMock 173123 +173123 ✅ NEW
ERC20FlashMintMock 158846 +158846 ✅ NEW
ERC3156FlashBorrowerMock 25789 +25789 ✅ NEW

This comment was generated automatically from benchmark diffs.

@codecov
Copy link
Copy Markdown

codecov bot commented Dec 10, 2025

Codecov Report

❌ Patch coverage is 92.85714% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.00%. Comparing base (315a00a) to head (5f0ae51).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
.../token/src/erc20/extensions/erc20_flash_mint.cairo 92.30% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1608      +/-   ##
==========================================
- Coverage   94.01%   94.00%   -0.02%     
==========================================
  Files          96       98       +2     
  Lines        2391     2419      +28     
==========================================
+ Hits         2248     2274      +26     
- Misses        143      145       +2     
Files with missing lines Coverage Δ
packages/interfaces/src/token/erc20.cairo 100.00% <ø> (ø)
packages/interfaces/src/token/erc3156.cairo 100.00% <100.00%> (ø)
.../token/src/erc20/extensions/erc20_flash_mint.cairo 92.30% <92.30%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 315a00a...5f0ae51. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Collaborator

@immrsd immrsd left a comment

Choose a reason for hiding this comment

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

Looking good and consistent with the Solidity implementation!
Left a couple of comments

@bidzyyys bidzyyys requested review from bidzyyys and Copilot March 10, 2026 15:34
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 10, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cd47c10a-d81f-44b1-be34-d15d41769efe

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This pull request introduces ERC-3156 Flash Mint support for ERC20 tokens, including new Starknet interfaces for flash lenders and borrowers, a component implementation enabling flash loans, mock contracts for testing, and a comprehensive test suite validating the flash loan workflow.

Changes

Cohort / File(s) Summary
Interface Definitions
packages/interfaces/src/lib.cairo, packages/interfaces/src/token.cairo, packages/interfaces/src/token/erc3156.cairo
Added ERC-3156 interface module exports. New file defines IERC3156FlashLender and IERC3156FlashBorrower traits with flash loan methods (max_flash_loan, flash_fee, flash_loan, on_flash_loan).
Core Implementation
packages/token/src/erc20/extensions.cairo, packages/token/src/erc20/extensions/erc20_flash_mint.cairo
Added ERC20FlashMintComponent with FlashMintConfigTrait for customizable flash loan behavior. Implements IERC3156FlashLender orchestrating flash loan flow: validation, minting, callback invocation, fee handling, and repayment enforcement.
Test Infrastructure
packages/test_common/src/mocks/erc20.cairo, packages/token/Scarb.toml
Added three mock contracts: ERC20FlashMintMock, ERC20FlashMintConfiguredMock (with configurable parameters), and ERC3156FlashBorrowerMock. Updated Scarb.toml to include new mocks in external contracts build list.
Test Suite
packages/token/src/tests/erc20.cairo, packages/token/src/tests/erc20/test_erc20_flash_mint.cairo
Added comprehensive flash mint test module with 240 lines covering max_flash_loan behavior, fee calculations, flash_loan execution, fee receiver handling, and validation of receiver approvals and magic value returns.
Documentation
CHANGELOG.md, packages/interfaces/src/token/erc20.cairo
Updated changelog with ERC-3156 feature entry. Removed blank line in ERC20 interface file.

Sequence Diagram

sequenceDiagram
    participant Initiator as Initiator<br/>(Flashloan Caller)
    participant Lender as ERC20FlashMint<br/>(Lender)
    participant Token as ERC20<br/>(Token)
    participant Receiver as Borrower<br/>(Receiver Contract)

    Initiator->>Lender: flash_loan(receiver, token, amount, data)
    Lender->>Lender: Validate amount ≤ max_flash_loan
    Lender->>Lender: Calculate fee
    Lender->>Token: mint(receiver, amount)
    rect rgba(100, 150, 200, 0.5)
        Lender->>Receiver: on_flash_loan(initiator, token, amount, fee, data)
        Receiver->>Token: transfer/approve operations
        Receiver-->>Lender: return magic value
    end
    Lender->>Lender: Validate return value & approvals
    Lender->>Token: burn amount or transfer to fee_receiver
    Lender-->>Initiator: true (success)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • bidzyyys
  • immrsd

Poem

🐰 Flash loans swift as rabbit feet,
ERC-3156 makes DeFi neat,
Mint and burn in one quick dance,
Fee configs give contracts a chance!
Borrow, repay, no time to waste—
Flash mint features fueled by taste! 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'ERC20 flash mint extension' directly and clearly describes the main change: implementing a flash mint extension for ERC20.
Linked Issues check ✅ Passed The PR fully implements the ERC-20 FlashMint extension requested in issue #1577, including interfaces (IERC3156FlashLender and IERC3156FlashBorrower), component implementation with configurable behavior, comprehensive tests, and proper integration into the codebase.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the ERC-20 FlashMint extension. Changes include interface definitions, component implementation, test mocks, tests, and necessary build configuration updates. No unrelated changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/erc20-flash-mint-#1577

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements the ERC-20 Flash Mint Extension following the ERC-3156 standard for flash loans (issue #1577). It adds a new ERC20FlashMintComponent that allows ERC20 tokens to offer single-transaction flash loans by minting tokens to a borrower and burning them back (plus an optional fee) within the same transaction.

Changes:

  • New ERC20FlashMintComponent implementing IERC3156FlashLender with configurable fee logic via FeeConfigTrait
  • New IERC3156FlashLender and IERC3156FlashBorrower interface definitions
  • Module registration in extensions.cairo and token.cairo

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
packages/token/src/erc20/extensions/erc20_flash_mint.cairo Core flash mint component implementation
packages/token/src/erc20/extensions.cairo Registers the new erc20_flash_mint module
packages/interfaces/src/token/erc3156.cairo Defines IERC3156FlashLender and IERC3156FlashBorrower interfaces
packages/interfaces/src/token.cairo Registers the new erc3156 module
packages/interfaces/src/token/erc20.cairo Minor blank-line cleanup only

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@ericnordelo ericnordelo marked this pull request as ready for review March 16, 2026 14:21
@ericnordelo ericnordelo requested a review from immrsd March 16, 2026 14:22
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/token/src/tests/erc20/test_erc20_flash_mint.cairo (1)

152-155: Extract duplicated borrower funding setup into a helper.

The pre-funding sequence is duplicated; pulling it into one helper will keep tests leaner.

♻️ Suggested refactor
+fn fund_borrower(token: ContractAddress, borrower: ContractAddress, amount: u256) {
+    let token_dispatcher = erc20(token);
+    start_cheat_caller_address(token, OWNER);
+    assert!(token_dispatcher.transfer(borrower, amount));
+    stop_cheat_caller_address(token);
+}
+
 #[test]
 fn flash_loan_burns_fees_when_fee_receiver_is_zero() {
@@
-    start_cheat_caller_address(token, OWNER);
-    assert!(token_dispatcher.transfer(borrower, FLASH_FEE));
-    stop_cheat_caller_address(token);
+    fund_borrower(token, borrower, FLASH_FEE);
@@
 #[test]
 fn flash_loan_transfers_fee_to_fee_receiver() {
@@
-    start_cheat_caller_address(token, OWNER);
-    assert!(token_dispatcher.transfer(borrower, FLASH_FEE));
-    stop_cheat_caller_address(token);
+    fund_borrower(token, borrower, FLASH_FEE);

Also applies to: 177-180

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/token/src/tests/erc20/test_erc20_flash_mint.cairo` around lines 152
- 155, Extract the duplicated pre-funding sequence into a helper (e.g.,
prefund_borrower) that wraps start_cheat_caller_address(token, OWNER); asserts
token_dispatcher.transfer(borrower, FLASH_FEE); and calls
stop_cheat_caller_address(token); then replace both occurrences (the block using
start_cheat_caller_address/transfer/stop_cheat_caller_address at lines around
the two test spots) with a single call to that helper to keep tests DRY.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/token/src/tests/erc20/test_erc20_flash_mint.cairo`:
- Around line 152-155: Extract the duplicated pre-funding sequence into a helper
(e.g., prefund_borrower) that wraps start_cheat_caller_address(token, OWNER);
asserts token_dispatcher.transfer(borrower, FLASH_FEE); and calls
stop_cheat_caller_address(token); then replace both occurrences (the block using
start_cheat_caller_address/transfer/stop_cheat_caller_address at lines around
the two test spots) with a single call to that helper to keep tests DRY.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7ccd6fa2-45e2-4e86-b47c-841ee045bdea

📥 Commits

Reviewing files that changed from the base of the PR and between cdd7ce7 and b91972c.

📒 Files selected for processing (11)
  • CHANGELOG.md
  • packages/interfaces/src/lib.cairo
  • packages/interfaces/src/token.cairo
  • packages/interfaces/src/token/erc20.cairo
  • packages/interfaces/src/token/erc3156.cairo
  • packages/test_common/src/mocks/erc20.cairo
  • packages/token/Scarb.toml
  • packages/token/src/erc20/extensions.cairo
  • packages/token/src/erc20/extensions/erc20_flash_mint.cairo
  • packages/token/src/tests/erc20.cairo
  • packages/token/src/tests/erc20/test_erc20_flash_mint.cairo
💤 Files with no reviewable changes (1)
  • packages/interfaces/src/token/erc20.cairo

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Copy link
Copy Markdown
Collaborator

@bidzyyys bidzyyys left a comment

Choose a reason for hiding this comment

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

LGTM

self: @ComponentState<TContractState>, token: ContractAddress, total_supply: u256,
) -> u256 {
let this = get_contract_address();
if token != this {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can't you have it one line if token != get_contract_address() {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I would argue is easier to read for our users like this, since it maight not be quick getting what get_contract_address represent, but no strong opinion.

Copy link
Copy Markdown
Collaborator

@immrsd immrsd left a comment

Choose a reason for hiding this comment

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

Looking good! Left a few minor suggestions
What's the plan on adding support for the component in with_components macro, will it be done in a separate PR?

@ericnordelo
Copy link
Copy Markdown
Member Author

Looking good! Left a few minor suggestions
What's the plan on adding support for the component in with_components macro, will it be done in a separate PR?

separate PR for the sake of me prioritizing the macro refactor.

@immrsd immrsd self-requested a review March 31, 2026 10:06
@immrsd
Copy link
Copy Markdown
Collaborator

immrsd commented Mar 31, 2026

LGTM!

@ericnordelo ericnordelo merged commit 5452a72 into main Mar 31, 2026
13 checks passed
@ericnordelo ericnordelo deleted the feat/erc20-flash-mint-#1577 branch March 31, 2026 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add ERC-20 FlashMint Extension

4 participants