Skip to content

Conversation

@AndeLabs
Copy link

@AndeLabs AndeLabs commented Dec 3, 2025

Description

Implements Celo-style token duality pattern allowing native tokens to function as ERC-20 compatible tokens without wrapping.

Type of Change

  • New feature (non-breaking change which adds functionality)

Features

  • Native token transfers via precompile at 0x00..00FD
  • Admin + allowlist authorization model
  • Per-call and per-block transfer rate limiting
  • Chainspec configuration for admin and caps

The precompile provides the transfer mechanism; full ERC-20 compatibility requires a wrapper contract that calls this precompile and provides standard ERC-20 views and events.

Checklist

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Testing

  • 30 unit tests covering all functionality
  • All workspace tests passing
  • Clippy clean (no new warnings)
  • Documentation builds without warnings

References

@AndeLabs AndeLabs requested a review from a team as a code owner December 3, 2025 19:57
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @AndeLabs, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request delivers a significant new feature by implementing a "Token Duality" precompile, inspired by the Celo blockchain. This precompile allows native tokens to be transferred using an ERC-20-like interface, streamlining integration with smart contracts without requiring native tokens to be wrapped. It includes robust security features such as admin and allowlist-based access control, as well as per-call and per-block rate limiting to manage token flow. The configuration for this precompile, including its administrator and transfer limits, is now fully manageable through the chainspec.

Highlights

  • New Token Duality Precompile: Introduces a precompile at address "0x00..00FD" that enables native tokens to behave like ERC-20 tokens without wrapping, following the Celo pattern.
  • Authorization Model: Implements an admin and allowlist-based authorization system for controlling who can initiate native token transfers via the precompile.
  • Rate Limiting: Adds configurable per-call and per-block transfer caps to prevent large-scale token movements and enhance security.
  • Chainspec Configuration: Allows the admin address and rate limiting caps for the Token Duality precompile to be configured via the chainspec.
  • Dependency Update: Integrates the "parking_lot" crate for efficient and thread-safe block-level transfer tracking within the precompile.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new TokenDuality precompile, enabling native tokens to function as ERC-20 compatible tokens, following the Celo pattern. The implementation is comprehensive, with thorough documentation, extensive unit tests, and proper integration into the EVM factory and node configuration. The code is of high quality. I've provided a couple of minor suggestions to improve consistency and readability in the precompile implementation.

Comment on lines 400 to 417
fn add_balance(
internals: &mut EvmInternals<'_>,
addr: Address,
amount: U256,
) -> Result<(), PrecompileError> {
let account = internals
.load_account(addr)
.map_err(Self::map_internals_error)?;

// SECURITY: Verify addition won't overflow before mutating state.
// The checked_add result is used for validation, then balance_incr
// performs the actual mutation (which is safe after this check).
let _new_balance = account
.info
.balance
.checked_add(amount)
.ok_or_else(|| PrecompileError::Other("balance overflow".to_string()))?;

internals
.balance_incr(addr, amount)
.map_err(Self::map_internals_error)?;
Ok(())
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

For consistency and clarity, this function can be implemented similarly to sub_balance. Using set_balance with the pre-checked new_balance avoids a potential double-load of the account that balance_incr might perform and makes the overflow protection more explicit within the state mutation logic.

    fn add_balance(
        internals: &mut EvmInternals<'_>,
        addr: Address,
        amount: U256,
    ) -> Result<(), PrecompileError> {
        let account = internals
            .load_account(addr)
            .map_err(Self::map_internals_error)?;

        // SECURITY: Verify addition won't overflow before mutating state.
        let new_balance = account
            .info
            .balance
            .checked_add(amount)
            .ok_or_else(|| PrecompileError::Other("balance overflow".to_string()))?;

        internals
            .set_balance(addr, new_balance)
            .map_err(Self::map_internals_error)?;
        Ok(())
    }

Comment on lines 520 to 524
fn allowlist_key(addr: Address) -> U256 {
U256::from_be_bytes(addr.into_word().into())
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The alloy_primitives::U256 type implements From<Address>, which provides a more idiomatic and readable way to convert an Address into a U256 for use as a storage key. This simplifies the code and relies on the tested conversion logic from the alloy library.

    fn allowlist_key(addr: Address) -> U256 {
        U256::from(addr)
    }

@AndeLabs AndeLabs force-pushed the feat/token-duality-precompile branch 4 times, most recently from 51880de to ee1fc87 Compare December 3, 2025 20:15
Implements Celo-style token duality pattern allowing native tokens to
function as ERC-20 compatible tokens without wrapping.

Features:
- Native token transfers via precompile at 0x00..00FD
- Admin + allowlist authorization model
- Per-call and per-block transfer rate limiting
- Chainspec configuration for admin, caps and activation height

The precompile provides the transfer mechanism; full ERC-20 compatibility
requires a wrapper contract that calls this precompile and provides
standard ERC-20 views and events.
@AndeLabs AndeLabs force-pushed the feat/token-duality-precompile branch from ee1fc87 to 0060389 Compare December 5, 2025 02:22
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.

1 participant