Skip to content

Conversation

edwardchew97
Copy link

@edwardchew97 edwardchew97 commented Aug 13, 2025

Rendered NEP: https://github.com/Meteor-Wallet/NEPs/blob/master/neps/nep-0621.md
Reference implementations: https://github.com/Meteor-Wallet/tokenized-vault-nep-implementation


NEP Status (Updated by NEP Moderators)

Status: Needs WG to assign SME

@edwardchew97 edwardchew97 requested a review from a team as a code owner August 13, 2025 13:19
@github-project-automation github-project-automation bot moved this to NEW in NEPs Aug 13, 2025
@github-project-automation github-project-automation bot moved this to NEW❗ in DevRel Aug 13, 2025
@edwardchew97 edwardchew97 changed the title NEP-xxx: Tokenized Vault NEP-0621: Tokenized Vault Aug 13, 2025
@edwardchew97 edwardchew97 changed the title NEP-0621: Tokenized Vault NEP-621: Tokenized Vault Aug 13, 2025
@edwardchew97
Copy link
Author

edwardchew97 commented Aug 13, 2025

@near/nep-moderators This NEP is ready to be reviewed.

@garikbesson
Copy link
Contributor

Hi @edwardchew97, thank you for bringing new ideas and helping to push the entire ecosystem forward!

As a NEP moderator, I reviewed your proposal, and there is only one thing I would like to ask you - please, remove the Unresolved Issues (Optional) section from the proposal, since it's optional and hasn't been filled in.

Other than that, everything looks fine, and as soon as you push the requested changes, I will ask WG to assign SMEs to review the proposal.

@garikbesson garikbesson added S-draft/needs-author-revision A NEP in the DRAFT stage that needs an author revision. A-NEP A NEAR Enhancement Proposal (NEP). labels Aug 13, 2025
@garikbesson garikbesson moved this from NEW to DRAFT in NEPs Aug 13, 2025
@edwardchew97
Copy link
Author

edwardchew97 commented Aug 14, 2025

Hi @garikbesson, thanks for pointing that out — I have removed it as requested.

@garikbesson garikbesson added WG-contract-standards Contract Standards Work Group should be accountable S-review/needs-wg-to-assign-sme A NEP that needs working group to assign two SMEs. and removed S-draft/needs-author-revision A NEP in the DRAFT stage that needs an author revision. labels Aug 15, 2025
@garikbesson garikbesson moved this from DRAFT to REVIEW in NEPs Aug 15, 2025
@garikbesson
Copy link
Contributor

As a moderator, I'm asking @near/wg-contract-standards working group members to assign 2 Technical Reviewers to complete a technical review of the proposal.

Copy link

@IkerAlus IkerAlus left a comment

Choose a reason for hiding this comment

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

Hi @edwardchew97 thanks for the good work. I have done a general review of the proposal (not the implementation) and compared it with original ERC4626 specification, and I have a couple of comments:

  • The proposal is missing deposit and mint methods. Is there any reason for this? AFAIK, these two methods are main state-changing flows in ERC4626.
  • In ERC4626, totalAssets view method states that it MUST be inclusive of any fees that are charged against assets in the Vault. Can you add this statement too?
  • Can you add the event emitted to the corresponding method description? For example, withdraw method should emit withdraw event.
  • Same you did for max_redeem, with "Implementations should return 0 if...", can you add a similar statement for maxWithdraw method as done in ERC4626?
  • Can you add when a method must or not revert (like it is done in the ERC4626)?
  • Finally, in "Alternatives" it is mentioned this spec is not a "direct clone ERC-4626 clone without NEAR Adjustments". Are this adjustments purely in the implementation? If they affect the spec, can you add a section stating which methods differ from ERC-4626 spec and how?

@edwardchew97
Copy link
Author

edwardchew97 commented Aug 27, 2025

@IkerAlus Thanks a lot for the thorough review! Addressed all your points below:

  • The proposal is missing deposit and mint methods. Is there any reason for this? AFAIK, these two methods are main state-changing flows in ERC4626.
  • Good catch — deposits/mints happen through ft_on_transfer. That was already in the implementation but not explicitly mentioned in the NEP. We’ve now added it to the spec for clarity.
  • In ERC4626, totalAssets view method states that it MUST be inclusive of any fees that are charged against assets in the Vault. Can you add this statement too?
  • Added this to the spec, thanks!
  • Can you add the event emitted to the corresponding method description? For example, withdraw method should emit withdraw event.
  • Great suggestion — events are now included in the method descriptions.
  • Same you did for max_redeem, with "Implementations should return 0 if...", can you add a similar statement for maxWithdraw method as done in ERC4626?
  • Added that as well.
  • Can you add when a method must or not revert (like it is done in the ERC4626)?
  • Updated the spec accordingly (no changes in the reference implementation).
  • Finally, in "Alternatives" it is mentioned this spec is not a "direct clone ERC-4626 clone without NEAR Adjustments". Are this adjustments purely in the implementation? If they affect the spec, can you add a section stating which methods differ from ERC-4626 spec and how?
  • Yes, most of the adjustments are only in the implementation and not shown on the interfaces. The differences are primarily due to the asynchronous nature of NEAR Protocol. This doesn’t necessarily prevent ERC-4626 atomic actions from working (with risk) but introduces some implementation-level nuances (e.g. total_assets). Beyond that, most choices are left to the developer, so we’ve opted to keep these adjustments in the implementation rather than the core spec. That said, we’ve added further clarification under the section. Appreciate you pointing this out too.

Copy link

@IkerAlus IkerAlus left a comment

Choose a reason for hiding this comment

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

hey @edwardchew97 thanks for the thorough and detailed answers. I think the spec looks almost ready to go. I only have one main comment, the rest are format changes and clarifications.

neps/nep-0621.md Outdated
````

```rust
pub trait VaultOptionalSlippageWithdraw {

Choose a reason for hiding this comment

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

are these two new methods mandatory in the NEP or just recommended?

I see they add a very valid use case but they are not part of ERC4626

neps/nep-0621.md Outdated

````rust
pub trait FungibleTokenReceiver {
/// According to the NEP-141 standard, all fungible token transfers to a contract
Copy link

@IkerAlus IkerAlus Aug 29, 2025

Choose a reason for hiding this comment

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

can we take out this explanation (from line 324 to 349) and place it just below "Deposit and Mint" subsection?

neps/nep-0621.md Outdated
}
```

Deposit and Mint

Choose a reason for hiding this comment

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

shouldn't this section be placed inside the "Contract Interface" section and not inside "Events" section?

neps/nep-0621.md Outdated
/// correctly handle `ft_on_transfer` according to NEP-141:
/// - Return `PromiseOrValue::Value(0)` if all tokens were accepted.
/// - Return a non-zero `U128` to indicate the number of tokens to refund.
fn ft_on_transfer(&mut self, sender_id: AccountId, amount: U128, msg: String) -> PromiseOrValue<U128>

Choose a reason for hiding this comment

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

Both deposit and mint should emit a VaultDeposit event. Something you indeed do in the ref impl in https://github.com/Meteor-Wallet/tokenized-vault-nep-implementation/blob/5952f914a4f1601aa73ac142d77af45685309933/src/lib.rs#L276

This should be specified in the spec doc too for completeness.

Copy link

@IkerAlus IkerAlus left a comment

Choose a reason for hiding this comment

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

@edwardchew97 and @SteveKok great work with the specification of the NEP and thanks for addressing all my comments.

hey @frol @gagdiez can we find a couple of reviewers for the specification and also proposed implementation of this NEP?

@garikbesson
Copy link
Contributor

@frol @robert-zaremba @fadeevab @mfornet

Hi guys,

The proposal is ready to be reviewed by SMEs, therefore, I'm asking @near/wg-contract-standards working group members to assign 2 Technical Reviewers to complete a technical review of the proposal.

According to the NEPs Guidelines, if the reviewed NEP is not approved within two months, it is automatically rejected.

For the presented proposal, this 2-month period starts from 15th August.

@robert-zaremba
Copy link
Contributor

I can have a look

Copy link
Contributor

@fadeevab fadeevab left a comment

Choose a reason for hiding this comment

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

Hi! I left two suggestions, check it out.

/// Returns the total amount of underlying assets represented by all shares in existence.
///
/// **Important:**
/// - Represents the vault's *total managed value*, not just assets held in the contract.
Copy link
Contributor

@fadeevab fadeevab Sep 22, 2025

Choose a reason for hiding this comment

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

I understand where it comes from, but two "asset"/"assets" terms create a wild confusion. "Asset" means FT address, and "assets" means "amount of that one underlying asset (FT token)". Perhaps, it could be better addressed, e.g. "assets" could be called as "underlying asset's amount" in the docs comments.

neps/nep-0621.md Outdated
/// Redeem a specific number of shares, **only if** they are worth
/// at least `min_amount` of assets.
/// This acts as a slippage-protected version of `redeem`.
fn redeem_with_slippage(
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems both redeem and withdraw must have slippage control via min_amount parameter by default on NEAR, without "optional for security" redeem/withdraw_with_slippage counterparts. Because NEAR is fundamentally asynchronous in execution, and because this NEP is adaptation to NEAR's reality, it's worth to introduce secure by default methods, not vice versa.

@fadeevab
Copy link
Contributor

@SteveKok Thanks for these improvements!

Now, we still have assets method arguments, but I'm not sure about the necessity of renaming all of them to asset_amount. Although the new function names are great, they create discrepancies between this NEP and ERC. 🤔 I'm not sure how to address this; perhaps it would be better just to leave a note that "asset is this" and "assets is that", while preserving the ERC's API. Or finish renaming of the rest of assets to asset_amount to make the whole NEP clearer.

Take my suggestions about naming/renaming of assets with a grain of salt!

Other than that, the NEP looks good 👍

@SteveKok
Copy link

@SteveKok Thanks for these improvements!

Now, we still have assets method arguments, but I'm not sure about the necessity of renaming all of them to asset_amount. Although the new function names are great, they create discrepancies between this NEP and ERC. 🤔 I'm not sure how to address this; perhaps it would be better just to leave a note that "asset is this" and "assets is that", while preserving the ERC's API. Or finish renaming of the rest of assets to asset_amount to make the whole NEP clearer.

Take my suggestions about naming/renaming of assets with a grain of salt!

Other than that, the NEP looks good 👍

@fadeevab thanks for raising this!

After reviewing, I noticed that the asset keyword is consistently used in quite a lot of places, such as:

  • asset_contract_id
  • asset_amount
  • convert_to_shares(&self, assets: U128)
  • preview_deposit(&self, assets: U128)
  • withdraw(&mut self, assets: U128, max_shares_deducted: Option<U128>, receiver_id: Option<AccountId>)
  • preview_withdraw(&self, assets: U128)
  • VaultDeposit event
  • VaultWithdraw event

This leads me to think we should either:

  1. Rename them all to something more explicit like underlying_asset, or
  2. Keep them as asset to stay consistent.

After some digging, I realized we’ve actually been quite consistent conceptually:

  • share / shares → always represent the amount of FT minted for users
  • asset / assets → always represent the amount of the underlying tokens accepted

So the keyword asset on its own may already be meaningful enough in context.

The real confusion, in my opinion, comes from the overlap with ft terminology:

  • ft_balance_of → refers to shares
  • ft_transfer → refers to shares
  • ft_transfer_call → refers to shares
  • ft_on_transfer → refers to assets

That inconsistency between ft methods (shares) and asset methods (underlying tokens) is probably where users might get tripped up more than by the asset vs. assets wording.

So I’d lean towards keeping asset as is for clarity and ERC compatibility, and maybe just leaving a note in the NEP explaining:

  • "asset always means underlying tokens"
  • "shares always means the minted vault tokens"
  • "ft_* methods are about shares, except ft_on_transfer, which accepts assets."

This way we keep both clarity and alignment with existing standards.

@SteveKok
Copy link

@IkerAlus I noticed some differences between Solidity and Rust when defining interfaces.

In Solidity, an interface allows us to assign names to return values, which serve as lightweight documentation and make it clearer what each value represents.

In Rust traits, however, we can only specify the return type, without attaching descriptive names. Because of this, I’ve reworked many of the method names to be more self-explanatory, so that the intent of the return values is still clear even without named returns.

I’d appreciate it if you could review the updated naming choices and share your feedback.

Copy link
Contributor

@fadeevab fadeevab left a comment

Choose a reason for hiding this comment

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

Reviewed a little bit more. Check other places in the documentation comments for inconsistencies.

@IkerAlus
Copy link

IkerAlus commented Sep 25, 2025

hey @SteveKok Good point, I think it is a valid improvement and will help devs implementing and/on integrating with this contract standard. The NEP spec is all good after you fixed the inconsistencies as the last review pointed out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-NEP A NEAR Enhancement Proposal (NEP). S-review/needs-wg-to-assign-sme A NEP that needs working group to assign two SMEs. WG-contract-standards Contract Standards Work Group should be accountable
Projects
Status: NEW❗
Status: REVIEW
Development

Successfully merging this pull request may close these issues.

7 participants