Individual Contributor License Agreement

https://metamask.io/cla/

MetaMask Individual Contributor License Agreement (“Agreement”)

Thank you for your interest in MetaMask (“MetaMask”). In order to clarify the intellectual property license granted with Contributions from any person or entity, MetaMask must have a Contributor License Agreement (“CLA”) on file that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of MetaMask and its users; it does not change your rights to use your own Contributions for any other purpose.

You accept and agree to the following terms and conditions for Your present and future Contributions submitted to MetaMask. Except for the license granted herein to MetaMask and recipients of software distributed by MetaMask, You reserve all right, title, and interest in and to Your Contributions.

1. Definitions. “You” (or “Your”) shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with MetaMask. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, “control” means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. “Contribution” shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to MetaMask for inclusion in, or documentation of, any of the products owned or managed by MetaMask (the “Work”). For the purposes of this definition, “submitted” means any form of electronic, verbal, or written communication sent to MetaMask or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, MetaMask for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as “Not a Contribution.”

2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to MetaMask and to recipients of software distributed by MetaMask a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works.

3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to MetaMask and to recipients of software distributed by MetaMask a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed.

4. Authorization. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to MetaMask, or that your employer has executed a separate Corporate CLA with MetaMask.

5. Original Creation. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions.

6. No Support Obligation. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.

7. Licensed Works. Should You wish to submit work that is not Your original creation, You may submit it to MetaMask separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as “Submitted on behalf of a third-party: [named here]”.

8. Notification. You agree to notify MetaMask of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect.

Please sign:

__________________________________ Date: ________________

When can I withdraw my stake? How do I do it?

https://metamask.io/news/latest/when-can-i-withdraw-my-stake-how-do-i-do-it/

This article is a follow–up to a previous explainer, What is staking? How do I do it?
If you’re unfamiliar with the topic of staking, start there.

What are staking withdrawals? Well, to summarize: there are lots of things that people call “staking”; and in those situations where you’ve locked up tokens, or staked them, generally there’s a mechanism through which you can withdraw those deposited tokens, and get them back into an account you control. Usually there’s a button in the interface of the staking app UI that says “Unstake”, or “Withdraw”, or something to that effect; you sign a transaction, pay the gas, and you get your coins back.

That hasn’t been the case with true, Ethereum network-level staking, however. Take a look at our previous explanation:

Wait… What about when someone wants to pull out their ETH?

Liquid staking providers don’t currently offer this functionality, because they can’t. When the Ethereum network made the switch from Proof of Work to Proof of Stake, they focused on getting Proof of Stake running properly first, before moving on to the process by which users could withdraw already-staked ETH. For now, all staked ETH remains staked.

Withdrawal functionality is scheduled to be released in the Shanghai upgrade, which could happen during 2023. In the meantime, users wishing to get rid of their liquid staking tokens and “change them back” to ETH would have to do so through a swap, which they can do right from their MetaMask wallet by clicking or tapping the “Swap” button.

That Shanghai upgrade we mentioned? Well, it’s right around the corner: at time of writing, scheduled for April 12th.

What happens when I withdraw my stake?

The concept is simple, and it’s like we stated previously: you get your ETH back in an account you control. How that happens, and what’s involved, will vary widely depending on the way you staked your ETH. Let’s take a look at some nuances:

If you are a holder of Rocket Pool or Lido liquid staking tokens (rETH and stETH, respectively), you will be able to process your withdrawals through the MetaMask Staking feature of the Portfolio Dapp. Rocket Pool withdrawals are expected to be available as soon as the Shanghai upgrades have completed; Lido is currently implementing withdrawals, and we plan to support them in MetaMask Staking as soon as we can. In the meantime, you can swap your stETH for ETH, such as with MetaMask Swaps, if you wish.

Once the Shanghai upgrade goes live, you’ll still be able to swap your rETH or stETH for ETH, or other tokens, the way you can now. In addition, though, you’ll be able to use the protocol’s staking withdrawal mechanism right from Portfolio Dapp: you don’t even need to go to their website to process a withdrawal. Our full walkthrough on how the process works will be available here, in case you get stuck.

You also have the ability to stake more ETH in those protocols right from Portfolio Dapp, as well as swap them for other tokens, including ETH, even before the Shanghai upgrade occurs. For more information on this, we’ve got a whole section of articles explaining it all.

If you’re unclear on what “liquid staking” is, check out our section on the topic in our previous article.

One advantage of liquid staking is that you can decide how much to withdraw without worrying about keeping a validator node running; Rocket Pool and Lido take care of that. On the other hand–the more ETH we all collectively stake, the more secure the network is as a whole.

Custodial staking

If you’ve staked ETH with a custodial provider, such as a centralized exchange (CEX), you’ll want to be looking for communications from them about what the process will be like. Remember–if you’ve staked with a custodial provider, you’re relying on them to keep your stake safe, as opposed to self-custodial options, where you always hold the keys to your accounts.

Also keep in mind that, if you staked with a custodial provider, it’s possible that you’ve been given a liquid staking-style token in return, which that exchange has indicated is equivalent to the value of the ETH you staked. For example, Coinbase offers a token called cbETH.

If you, in fact, hold some liquid ETH staking tokens, such as Lido or Rocket Pool, you can stay up to date on your balances and your corresponding portion of the rewards earned by the protocol in the MetaMask Staking feature of the Portfolio Dapp (portfolio.metamask.io/stake).

Self-custodial

There are some providers whose setups allow you to stake full nodes, and still maintain custody of your keys. Again, how these individual providers will enable withdrawals will likely vary from one to another.

At our own ConsenSys Staking, for example, we will be offering users the ability to withdraw their stake both through a UI flow, as well as through API functionality. Users of MetaMask Institutional will also have the ability to process withdrawals from ConsenSys Staking as well as Allnodes, Blockdaemon, and Kiln, through their powerful Staking Marketplace.

Again–consult with your provider, and keep in mind the particularities listed below under “Self-run nodes”; depending on how your staking setup works, you may have some additional steps to enable withdrawals.

Self-run nodes

If you personally are running your own node and staking through it, either on your own computer or through a cloud service provider, then there are some things you should be aware of:

First, the caveat surrounding your node’s address credential type. This is technical, and has to do with changes that have been made to Ethereum address structures in the past few years, but it boils down to the fact that more than half of current stakers will need to take action to change to a different address format in order to withdraw their stake. For more detailed information on this, check out ConsenSys’ Ultimate Guide to ETH Staking Withdrawals.

You should also be aware of the two different types of withdrawals that will become available: full and partial.

  • Full: Just like it sounds, a full withdrawal is, essentially, ceasing to be a validator. You’ll be pulling the full ETH balance out of your node or nodes, and shutting down your node. In other words, 32 ETH x number of nodes + accumulated staking rewards.
  • Partial: With partial withdrawals, you will be able to withdraw ETH that your node has accumulated in terms of rewards–but leaving intact the requisite 32 staked ETH so that your node continues running.

If you’re running a node, or want to know more about how this will work, check out the Ethereum Foundation’s FAQs on withdrawals.

Keeping your stake, and your accounts, safe

There is a lot of conversation going on–in the news, on social media, and company blogs like this one–about the Shanghai upgrade. Big changes in Ethereum protocol like this always bring with them the opportunity for scammers that will try to trick you out of your ETH, and anything else you have in your wallet.

If you want to know how to protect yourself and your assets, and recognize common scam tactics, check out our Staying safe in web3 series: we update it more than we’d like to. Stay safe out there, and if you need anything, we’re here to help.

Buying Crypto in Portfolio Dapp For An Easy Experience, the MetaMask Way

https://metamask.io/news/latest/buying-crypto-in-portfolio-dapp-for-an-easy-experience-the-metamask-way/

In our ongoing quest to make MetaMask users’ lives easier, we are launching the Buy Crypto feature in Portfolio Dapp for an easy purchasing experience. Simply navigate to the Buy tab in the dapp, connect your MetaMask wallet, and load up with the crypto of your choice!

MetaMask Extension users will now be redirected to the Portfolio Dapp automatically when selecting the “Buy” button in the wallet.

The ideal quote

Buying crypto on Portfolio Dapp takes into account a number of variables to present you with a customized quote:

  • Region: Available to users in 189 countries.
  • Payment Method: Availability of payment methods will vary by location. Choose from debit or credit card, PayPal, Bank Transfer, or Instant ACH. Other payment methods will be added soon.
  • Token: 90+ tokens available to purchase across 8 networks (Ethereum, Polygon, Optimism, Arbitrum, Binance Smart Chain, Avalanche Contract Chain, Fantom, and Celo).
  • Amount: Based on the region you select and its various KYC laws, you could be subject to order limits.

Welcoming new users globally

Ever since launching the aggregator, MetaMask has been on a mission to partner with providers worldwide to help welcome anyone—regardless of where you are based—to web3.

In the past year, we’ve partnered with multiple organizations for an easy onboarding process:

And we’re working on adding more providers and payment methods to our convenient, secure, and easy-to-use aggregator service.

The aggregator can be accessed by directly connecting to Portfolio Dapp or selecting the BUY button in the MetaMask extension wallet which will redirect you to portfolio.metamask.io/buy

To fund your wallet:

  1. Connect your MetaMask wallet to portfolio.metamask.io
  2. Click “Buy” to get started
  3. Select your region
  4. Select payment method
  5. Select the token and network you want to purchase on (example: ETH on Ethereum)
  6. Enter the amount desired in fiat (example: $100 of ETH)
  7. Click “Get Quotes.” All quotes from the different available providers will be presented and select one to continue.
  8. You’ll be securely redirected to their website to complete the purchase and funds will be deposited in your MetaMask wallet.

Success. 🦊

In the spirit of making web3 accessible to all, we’re excited to bring this feature to the dapp for our global community. We hope you enjoy the frictionless experience, let us know what you think, and happy buying!

Building the Future of Customer Support with MetaMask Activity

https://metamask.io/news/latest/building-the-future-of-customer-support-with-metamask-activity/

MetaMask’s new Support tool, MetaMask Activity.

When I talk to people who aren’t “into crypto”, there’s a clear theme: “It’s really complicated; I don’t understand; there’s so much, I wouldn’t know where to start.”

It’s true, there is a lot of complexity in decentralized ledger technologies. They are a framework through which we can build extremely powerful and fine-tuned collaborative systems, and all that detail and structure is public. Systems this complex exist all around us, and we interact with them every day. But we’re not used to seeing their bones and veins; we’re used to being provided with a simplified version, “the part that concerns us”.


The process of understanding enough to even interact with public blockchain networks often requires reading arcane, technical texts and absorbing abstract mathematical concepts. With a learning curve this steep, those of us trying to make this technology make sense to users find ourselves in the position of providing education and training as often as actual technical support. As any teacher can tell you, that’s not easy, and it’s not quick.

Let’s take a step back, though: these new technologies offer an incredible opportunity from the perspective of support and privacy. We have, already, a database of all the actions a user has taken on any of their accounts, actions which can be recognized and categorized using software, saving countless hours of manual lookup on the part of the Support agent and the customer.

What’s more, we can have access to this information without the customer ever providing us with their name or their email address; the only thing we need is their public account address.

With this, we can provide live, contextual support for their specific issue while preserving their anonymity. We have no access to, authority or permissions over their accounts; we get only the information we need, and the power stays with the customer. This is the vision we have of the future of customer support which we have begun to build.

A user should not have to sacrifice their privacy simply to have their tech work properly, or to understand how to use it; nor should they sacrifice at the level of user experience. With the tools we have, we can provide contextually-driven information not only on par with traditional infrastructure, but superior to it.


The beginning to all this–the first step in this transformation of the power dynamics between customer and provider–is MetaMask Activity.

connect wallet

All MetaMask Activity needs to work is a public account address, entered either by typing it, copy-pasting it, or authenticating using MetaMask.

The user is then presented with a readout of the transaction history of the account in question. Going much farther than the standard “ledger-style” account readout, the app categorizes the transaction type and provides the user with information specific to the type of transaction they performed.

For example, the common DeFi flow of approving a DEX to have access to your tokens, then swapping with that token:

MMA approval and swap

Or another favorite, minting NFTs:

MMA NFTs

Notice that failed transaction, showing up in red.

Off the top of my head, it looks like the user smashed that “mint” button twice in a row, and only one transaction went through. But the user doesn’t have to take my word for it; they can click through to the article, or copy-paste the transaction hash (its unique ID) and search for more details on Etherscan:

MMA copy transaction

And yes, ERC-1155 tokens are supported:

MMA purchase

…as well as a wide variety of ERC-20 tokens:

MMA send and receive

MetaMask Activity has an additional tool which helps users chase down transactions that go wrong. Transactions that fail, get stuck, or are pending for long periods of time:

MMA transaction pending2

This initial version of MetaMask Activity offers this functionality on Ethereum Mainnet, and it sets the stage for functionality that can be built on top of it: address-authenticated, transaction-specific Support chat; multi-chain analysis; the potential for more advanced features like dapp permissions management and assisted account migration tools.


The idea for MetaMask Activity originated in a conversation between a Help Desk team manager, a product manager on our team, and myself, a technical writer. Our Support agents were spending massive amounts of time helping customers find, and understand how to look at, their own transactions on the blockchain; both the customers and the Support teams desperately needed a tool to help them.

What took this concept to the next level was ConsenSys’ internal hackathon, in the spring of 2022. A team of five volunteered to build it, from all over the world, and all over the company: engineers, a marketer, a project manager, and myself.

Over the course of a work week, we built not only a functional proof of concept of this application, but were able to communicate the ways that it would improve the working conditions of Support agents, reduce the average time to resolution of Support tickets, and empower users to self-solve and learn about this technology. Additionally, it would be a first-of-its-kind application showing the benefits of open blockchain networks for something as normal and day-to-day as customer support.


We hope that MetaMask Activity gives you some insight into what’s going on with your accounts and transactions, and how this technology works. We’re very much focused on the long-term potential of this product, and remember: if you get stuck, we’re only a few clicks away.

Try it out here: activity.metmask.io

MetaMask Mobile and Extension updates improve wallet experience with more control and transparency

https://metamask.io/news/latest/metamask-mobile-and-extension-updates-improve-wallet-experience-with-more-control-and-transparency/

MetaMask recently pushed updates on its mobile app and browser extension to improve load times and optimize the wallet experience. We’re committed to continuously making MetaMask more transparent, private, and ultimately safer for our community.

You’re not alone if you didn’t realize where the MetaMask Mobile browser tab was until someone pointed it out in the app. With the revamped UI, you can toggle between your wallet and browser in a single tap within MetaMask Mobile. Additionally, there is more control and transparency when it comes to choosing which of your accounts to connect or disconnect from dapps.

Previously, when you connected to a dapp, all the accounts in your wallet were automatically linked. Now you have the option to choose which accounts to connect with, and disconnecting individual accounts has become more straightforward.

Every account and dapp connection is maintained separately in browser tabs, even as new ones are opened. As a result, each account can be conveniently disconnected from its corresponding tab.

By organizing your MetaMask accounts, you have better control over their usage. For example, you may want to use Account 1 as your “public facing” account associated with your ENS, while using Account 2 for your DeFi degen activities that you want to keep private.

Now you can as they won’t be linked to each other. The new mobile permission updates put privacy at the helm as you reduce unnecessary exposure to dapps and external services.

💡 Pro tip: Connect to your favorite dapp in the mobile browser or learn core crypto concepts with MetaMask Learn on the go. 🤳

We’ve updated the MetaMask extension to maximize the control you have over your data, and limit the amount of user data sent to third-party services that are required to run the extension.

The primary changes to the wallet experience are during onboarding and within the “Security and Privacy” settings:

  • You are prompted to confirm the first three words of your Secret Recovery Phrase (SRP) when creating a MetaMask wallet
  • You can choose any RPC provider during onboarding and opt out of our default, Infura.
  • You can disable certain features that send requests to third-party APIs under the “Advanced configuration” settings, giving you more control over your data. These options are on by default as they are additive to the experience, but can be turned off for any reason:
    • Incoming Transactions
    • Phishing Detection
    • Choosing custom network

More Control

MetaMask aims to be the standard bearer across crypto wallets for user privacy and security. Data exploitation goes against MetaMask core values. Instead, we believe in equipping our community with the founding principles that guide our development—true ownership and privacy.

We believe that part of the value MetaMask offers is the freedom to exit the product anytime. Self-custody means you truly control your private key, and can import that private key to any wallet interface that supports the standard Secret Recovery Phrase (SRP).

We are committed to protecting the privacy of our users so that you will not, and ultimately, cannot be exploited by yet another centralized entity.

The enhanced MetaMask Mobile UI makes navigating web3 on the go easier, and the evolved MetaMask Extension privacy opt-ins give you more agency over your data. We hope you enjoy the new experience!

And if you have any feature requests, let us know here.

MetaMask Security Monthly: March 2023

https://metamask.io/news/security/metamask-security-monthly-march-2023/

Security Laboratory

Screenshot 2023-04-05 at 2.13.46 PMFaith Lillibridge at the NORC console fifth floor, Columbia University Watson Lab, 1954.

Endo

  • Our attempts at plugging into webpack transforms without compromising the original import/export statements have been unsuccessful, unless we deconstruct webpack and utilize some of its parts as a framework for creating a bundler. However, we have decided to halt this endeavor and seek a more simplified solution. Therefore, we are experimenting with a new method in LavaMoat (see below).
  • The latest update to Endo compartment-mapper includes exitModuleImportHook, which allows for the dynamic importing of exit modules instead of requiring users to provide a pre-built list. This is the final significant feature required for compartment-mapper to serve as the backend for lavamoat-node.
  • Endo SES whitelist has received a minor update for React Native Android JSC in https://github.com/endojs/endo/pull/1511, bringing an old issue to a close https://github.com/endojs/endo/issues/660 (more recently https://github.com/LavaMoat/docs/issues/16) and being further looked into in https://github.com/react-native-community/jsc-android-buildscripts/issues/181.

LavaMoat

  • We are exploring an alternative method to secure bundling by utilizing a webpack loader to implement compartmentalization and adding the essential runtime later. This approach maintains the unchanged layers above the loaders, enabling most features such as treeshaking to operate seamlessly. However, the main hindrance to its success is the likelihood of custom plugins altering the code in unforeseen manners.
  • The scuttling security feature, which was introduced a while ago (#360), can now be applied to all potential same-origin child realms (eg. iframes) in the browser by configuring the experimental “scuttleGlobalThis” option combined with Snow (check out the progress #462.
  • React Native support has been resurrected/revived, beginning (again) with Endo SES lockdown integration (originally for RN v0.66.5), but now with RN v0.71.4 and MetaMask mobile app integration underway. Progress tracking epic: https://github.com/LavaMoat/docs/issues/12
  • Minor update to LavaMoat Browserify examples have be viewed in https://github.com/LavaMoat/LavaMoat/pull/476

🗣️ Talks! 🎙️

Better Dapps with Delegatable by Dan Finlay

Dan made his debut appearance at EthDenver by sharing his vision for how delegating can make building dapps safer and easier!

“There are a lot of people claiming airdrops and then getting all their money taken. That’s been kind of a repeating pattern … Delegatable lets you do anything you can do on a contract to another account. It’s got an open-ended caveat system so you can attenuate the ability you’re sharing in any way you want. And that can let you keep hot wallets cooler by limiting what they can do while allowing them to still do stuff on chain.”

JS Realms, Security Blank Spot by Gal Weizman

Join Gal as he discusses the increasing dangers of supply chain attacks that are associated with dependencies, and how Snow JS can help cover your back!

Topics include:

  • Evolution of the web
  • The importance of security and visibility
  • Third-party solutions
  • JavaScript Realms
  • Snow JS

Watch out for airdrop scams!

There has been a lot of dubious activity surrounding airdrops recently. MetaMask published an article in February about the dangers of rugpulls and airdrops, and we’d like to remind you that, as exciting as “free money” sounds, there are a number of ways that bad actors can use the practice to their advantage.

Always make sure you’re getting your information from the source. When unfounded rumors started popping up on social media that MetaMask was going to be taking a snapshot and/or airdrop on March 31, we alerted the community. Go to the source and be skeptical of internet strangers claiming to have “insider information.”

Days before the Arbitrum airdrop, an announcement was made by @ArkhamIntel when it was discovered that around 2400 wallets were targeted in anticipation of the event. In the aftermath, Coinbase covered just how many things can go wrong, with their coverage Arbitrum Shows Just How Messy (and Tricky) Crypto Airdrops Can Be.

Other stories about airdrop scams that occurred just in March include Polkadot, ShibaInu, and OpenAI DEFI (GPT-4).

Tales of Caution

And finally, you can view a basic rundown of how many of Monkey Drainer/Venom Drainer “Security Updates” contracts are deployed, victims count, total ETH and total USD / daily & total. Refresh the queries for current numbers. Brought to you by BlockmageAlchemyst.

MetaMask Security Monthly: February 2023

https://metamask.io/news/security/metamask-security-monthly-february-2023/

Security Laboratory

Screenshot 2023-03-07 at 4.28.36 PMEmmett Chappelle, renowned for his work in bioluminescence.

Endo

  • New approach to secure bundler – For the sake of plugging secure bundling into more existing bundlers in the ecosystem, the work gets split between two stages. One: a plugin to an existing tool (like webpack) to create a compartment map and transformed sources and save it as an app archive. Two: a bundler capable of turning an app archive into a secure bundle file. With that approach, adding support for a new bundling tool/ecosystem should require less work and be less likely to undermine the security aspects of the bundler. https://github.com/endojs/endo/pull/1449
  • Added attenuation for globals in policy. The basis for full compatibility with LavaMoat policies is ready for merging and shipping in compartment-mapper. A proof-of-concept attenuator implementing ‘write’ global policy was possible to introduce on top of that implementation. https://github.com/endojs/endo/pull/1491/

LavaMoat

  • Initial work on plugging into webpack to generate an Endo-compatible compartment map was started in https://github.com/LavaMoat/webpack-plugin-compartment-map
  • @lavamoat/snow Disabled creation of URL objects out of Blob/File to prevent bypass.
  • LavaMoat team helped with hardening functionality that’s exposed to MetaMask Snaps.
  • Research into unexpected iframe sandboxing side effects in Chrome.

The Good News

Eth_sign Disabled by Default; Toggle in Advanced Settings

MetaMask has observed a significant trend of phishing kits that abuse eth-sign to ask users to inadvertently sign malicious transactions. In the interest of striking an appropriate balance between user protection and user autonomy, MetaMask has disabled eth_sign by default but will allow you to toggle it back on in the advanced settings. You can read more about it in our extension PR.

Recently, Devin Shin, a technical support engineer for MetaMask, reported:
“I was working with a user on a security ticket and wanted to share this. They provided me with an obvious scam site which I investigated. At first, I was confused as to the vector of phishing because nothing was happening while trying to interact with the site. I checked the console logs, and it was clear that the site attempted to prompt an eth_sign txn, which failed due to the recent change. Happy to see this change having a positive effect!”

Ding Dong, The Monkey Drainer is Dead! While we can’t say for certain, this change may have contributed to the end of the dreaded Monkey Drainer NFT phishing group.

Update

📧 Namecheap/SendGrid Email Breach 🎣

You may have received an email purporting to come from MetaMask a couple weeks ago, which asked users to enter their secret recovery phrases. You also might have seen our tweet warning about the high-profile phishing attempt, and reminding users MetaMask does not collect KYC info and will never email you about your account.

We have determined that the breach did not affect MetaMask directly, but the attackers were able to send MetaMask-branded phishing emails from the NameCheap domain. NameCheap initially stated that they believed the breach to have occurred with their upstream service provider, SendGrid. They later released the following statement on their blog, though both statements seem to have been withdrawn at the time of writing this on Feb 28.

Read more from Bleeping Computer.

Screenshot 2023-03-07 at 4.29.17 PM

Tales of Caution

Google Fi hack victim had Coinbase, 2FA app hijacked by hackers
Another harrowing SIM swap tale. Cell phone provider Google Fi informed the user “hackers had stolen some customers’ information, likely connected to the recent breach at T-Mobile.” Things appear to have been resolved for now, but there are still many unanswered questions surrounding how safe this user’s and other Google Fi customers’ phones actually are. Read more from TechCrunch.

Fake Ethereum Denver website linked to notorious phishing wallet
Don’t trust Google Ads!
In the leadup to one of the biggest events in the Ethereum ecosystem, would-be EthDenver attendees were a prime target for scammers who went “as far as paying for a Google advertisement to promote the malicious website’s URL.” Always be certain you know the authenticity of any source you connect your wallet to, and generally avoid any sponsored Google search results. Read more from Cointelegraph.

Beware of Social Engineering

MetaMask Security Monthly: January 2023

https://metamask.io/news/security/metamask-security-monthly-january-2023/

Security Laboratory

Screenshot 2023-02-03 at 1.58.06 PMScientist at a fast neutron chopper at the Brookhaven Graphite Research Reactor (BGRR), 1953

LavaMoat

  • New features in @lavamoat/viz – now you can explore your dependencies in VR
  • Scuttling globals has been introduced into MetaMask extension development branch. MetaMask will soon ship with most powerful functionality removed from window of the extension UI by default. As a result, even if a malicious React component could find a way to reach window, the powerful functions would already be gone.
  • @lavamoat/snow security tool for realms now supports all major browsers in its latest release. By relying on the new version, MetaMask now has full visibility to all realms on both Chrome and Firefox.
  • Introducing @lavamoat/lavatube – a new tool in the LavaMoat toolbox allowing you to recursively visit every property of every value accessible from any given starting reference. In our research team we already use LavaTube to identify dangerous leakages made by objects and APIs we are trying to defend in our apps!

Endo

  • Final review of the first iteration of LavaMoat-style policy support is in progress. Minor features need to be added after that for full feature parity with LavaMoat policies, but no breaking changes are planned.
  • An early implementation of a secure bundler which controls scopes without relying on eval is also in review.

💀 Address Poisoning 💀

Can you spot the difference between these two addresses?

Screenshot 2023-02-03 at 2.01.37 PM

No? That’s what the scammers are counting on! There are a lot of letters and numbers in these hexadecimal addresses. Read more about how to avoid falling for the address poisoning that has been on the rise.

Deep Dive on Read-Only Reentrancy

Check out this well-thought-out Twitter thread on an attack vector that Solidity devs need to be aware of. We see you, @bytes032!

We look forward to seeing more from the new Web3Security DAO’s participants, like @bytes032, which has a state mission to “…empower individuals to excel in the field of web3 security by fostering a supportive and collaborative learning environment…”

Tales of Caution

Friendly reminder from our friends at Wallet Guard – be careful with downloads.

And for you gamers out there:

MetaMask Security Monthly: December 2022

https://metamask.io/news/security/metamask-security-monthly-december-2022/

Security Laboratory

Screenshot 2022-12-22 at 10.51.00 AMThe Patent Papers for Hedy Lamarr’s Secret Communication System, 1942

LavaMoat

@lavamoat/allow-scripts released with —experimental-bins flag to protect npm and yarn1 from bin confusion attacks. More on Bin Confusion: https://socket.dev/blog/npm-bin-script-confusion

Endo

The work on bundling intensifies. Various compatibility fixes are getting us closer to being able to use the compartment-mapper bundler for actual projects. Initial proof-of-concept of CommonJS support passes tests.

Node.js SWG’s Permission Model Proposal🤝

The Node.js Security Working Group has prepared a first proposal for their Permission Model to complement their Policy system. Their goal is similar to LavaMoat in that they aim to reduce system access exposed to semi-trusted third party code. Their approach is similar to Deno’s Permissions System in that it configures system access at the process level. LavaMoat enables more granular isolation, configuring system access at the package level within a process. When the Nodejs Permission Model has matured and been released, it should be useable in conjunction with LavaMoat to provide superior supply chain protection. We applaud the efforts of the Node.js Security Working Group and look forward to the evolution of the proposal!

Screenshot 2022-12-22 at 10.56.35 AM

Cautionary Tales

The Lazarus Group is at it again. Beware of fake crypto websites where you could inadvertently be downloading the Applejeus malware. Read more from Volexity as well as the Twitter thread below:

Social engineering continues to be one of the most nefarious tools for bad actors. This elaborate heist played out over weeks:

Thanks for Joining Us This Year

Whether this is the first MetaMask security report you’re reading or if you’ve been following along from our humble beginnings in April on Medium, we thank you for joining us. This year we’ve seen great progress from the Security Labs team on LavaMoat and Endo that we’ve detailed in these monthly reports, the launching of our HackerOne bug bounty program, and strategic campaigns to combat phishing.

Through the HackerOne program, we’ve developed relationships with over a hundred unique hackers who have helped us identify many vulnerabilities, leading to a safer MetaMask experience for all our users. We’re always welcoming more, so please be encouraged to get involved and go for those bounties!

Over the year, our friends at PhishFort have detected 19,571 attacks using the MetaMask branding and within the last 30 days have successfully taken down 1,873 campaigns. We also carried initiatives within both the browser extension and mobile app to block known-phishing of both MetaMask impersonation and other web3 brands, and will continue improving these efforts. The list we use is owned and managed by Consensys/MetaMask and updated multiple times per day.

There have also been exciting developments for MobyMask: A new initiative from the MetaMask team to help proactively protect users from phishing, which uses a dynamic web of trust for sourcing phishing reporters. Thanks to help from Laconic!

And we’re looking to grow the MetaMask security team next year, so keep an eye on the MetaMask open roles page!

Ether Eyes Snap: Predicting Future Gas Prices

https://metamask.io/news/developers/ether-eyes-snap-predicting-future-gas-prices/

MetaMask Snaps is the roadmap to making MetaMask the most extensible wallet in the world. As a developer, you can bring your features and APIs to MetaMask in totally new ways. Web3 developers are the core of this growth and this series aims to showcase the novel MetMask Snaps being built today.

Ether Eyes Snap

Snap Repo: https://github.com/aritroCoder/EtherEyes

Why did you build it?

Gas prices on the Ethereum blockchain can be really hard to predict, and is a hindrance when it comes to making payments. A user, when trying to make payments, can end up paying much more than required. Short time high traffic on the blockchain can lead to a huge impact in gas prices. Although L2s were built to reduce gas prices, we sometimes need a more general and easier solution than using an L2 for transaction purposes. We thought it would be useful for users to have an app that can predict future gas prices based on historical data and current trends.

Can you walk us through the technical implementation?

EtherEyes consists of four parts: Gas price server, the snap, SARIMA Model, web frontend. The gas price server provides data about historical and current gas prices. The website hosts the snap and provides interface to install and interact with the snap by calling snap API methods. We used Seasonal Autoregressive Integrated Moving Average(SARIMA) model to predict gas prices.

Gas Price Server

We collect live gas price data as a list of around 200 candlesticks (each candlestick is an aggregate of the past 30 minutes of data) using the Owlracle API. This gives us the timeseries data of past 100 hours of gas prices.

The Snap

For the snap, we used the transaction insights API to provide realtime gas prices predictions. The flow of the snap is as follows:

First, when the user starts a transaction, the transaction insights shows up in the confirmation page which is implemented using the onTransactionHandler. Here we show the user about upcoming prediction for next 30 and 60 mins. A simplified version of what we implemented is given here:

export const onTransaction: OnTransactionHandler = async ({ transaction }) => {
 let state: { notifToggle: boolean; urgency: number; lowEth: number };
 state = (await wallet.request({
   method: 'snap_manageState',
   params: ['get'],
 })) as { notifToggle: boolean; urgency: number; lowEth: number };
 if (!state) {
   state = {
     notifToggle,
     urgency,
     lowEth,
   };
 }
 let insights: any = {
   type: 'Gas Fee estimation',
 };
 if (
   !isObject(transaction) ||
   !hasProperty(transaction, 'data') ||
   typeof transaction.data !== 'string'
 ) {
   console.warn('unknown transaction type');
   return { insights };
 }
 const response = await fetch(`${MODEL_API_ENDPOINT}`, {
   method: 'get',
   headers: {
     'Content-Type': 'application/json',
   },
 });
 const currentData = await fetch(CURRENT_DATA_ENDPOINT, {
   method: 'get',
   headers: {
     'Content-Type': 'application/json',
   },
 });
 if (!response.ok) {
   throw new Error('API request failed');
 }
 const data = await response.json();
 const current = await currentData.json();
 state.lowEth = Math.min(data.low_30_minutes, data.low_60_minutes);
 await wallet.request({
   method: 'snap_manageState',
   params: ['update', state],
 });
 insights = {
   'Average Gas Limit': `Current value: ${current.avgGas}`,
   'Estimated current gas price': `Current value (Base + Priority): ${
     current.speeds[0].baseFee + current.speeds[0].maxPriorityFeePerGas
   } GWei; Base Fee: ${current.speeds[0].baseFee} GWei`,
   'Forecasted Avg Gas price (for the next 30 mins)': `
   Gas price within 30 minutes is expected to get as low as: ${data.low_30_minutes} GWei`,
   'Forecasted Avg Gas price (for the next 60 mins)': `Gas price within 60 minutes is expected to get as low as: ${Math.min(
     data.low_30_minutes,
     data.low_60_minutes,
   )} GWei`,
   'Expected savings in 30 mins (For average gas limit)': `
   ${
     current.avgGas *
     (current.speeds[0].baseFee +
       current.speeds[0].maxPriorityFeePerGas -
       data.low_30_minutes)
   } GWei`,
   'Expected savings in 60 mins (For average gas limit)': `${
     current.avgGas *
     (current.speeds[0].baseFee +
       current.speeds[0].maxPriorityFeePerGas -
       Math.min(data.low_30_minutes, data.low_60_minutes))
   } GWei
   `,
 };
 return { insights };
};

If the user deciedes to wait, he can wait and start a notification system from the website that interacts with the snap via onCronjob handler and sends gas prices after every three minutes as native browser notifications. When the prices get very close to the prediction, it asks the user to complete the transaction.


export const onCronjob: OnCronjobHandler = async ({ request }) => {
 switch (request.method) {
   case 'exampleMethodOne': {
     // get data from state whenever snap is invoked as snaps executions are ephemeral
     let state: { notifToggle: boolean; urgency: number; lowEth: number };
     state = (await wallet.request({
       method: 'snap_manageState',
       params: ['get'],
     })) as { notifToggle: boolean; urgency: number; lowEth: number };
     if (!state) {
       state = {
         notifToggle,
         urgency,
         lowEth,
       };
     }
     notifToggle = state.notifToggle;
     urgency = state.urgency;
     lowEth = state.lowEth;
     await wallet.request({
       method: 'snap_manageState',
       params: ['update', state],
     });
     console.log({ notifToggle });
     if (notifToggle) {
       const currentData = await fetch(CURRENT_DATA_ENDPOINT, {
         method: 'get',
         headers: {
           'Content-Type': 'application/json',
         },
       });
       const current = await currentData.json();
       if (Math.abs(current.speeds[0].baseFee - lowEth) < urgency / 38) {
         return wallet.request({
           method: 'snap_notify',
           params: [
             {
               type: 'native',
               message: `Gasfee is low! Pay now at ${current.speeds[0].baseFee} Gwei`,
             },
           ],
         });
       }
       return wallet.request({
         method: 'snap_notify',
         params: [
           {
             type: 'native',
             message: `Current gasfee is ${current.speeds[0].baseFee} Gwei`,
           },
         ],
       });
     }
     return 0; // basically do nothing
   }
   default:
     throw new Error('Method not found.');
 }
};

The corresponding cronjob settings are (in snap.manifest.json):

"endowment:cronjob": {
      "jobs": [
        {
          "expression": {
            "minute": "*/3",
            "hour": "*",
            "dayOfMonth": "*",
            "month": "*",
            "dayOfWeek": "*"
          },
          "request": {
            "method": "exampleMethodOne",
            "params": {}
          }
        }
      ]
    }

There is also an urgency feature that sets the urgency of the transaction (technically, the parameter that determines what should be the maximum difference between prediction and current gas prices so that the user should go on with the transaction). Changing the urgency varies this threshold. We implemented urgency setting using snap’s onRpcRequest method.


 export const onRpcRequest: OnRpcRequestHandler = async ({
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  origin,
  request,
}) => {
  switch (request.method) {
    // Other RPC methods here
    case 'set_urgency_35': {
      urgency = 35;
      let state: { notifToggle: boolean; urgency: number; lowEth: number };
      state = (await wallet.request({
        method: 'snap_manageState',
        params: ['get'],
      })) as { notifToggle: boolean; urgency: number; lowEth: number };
      if (!state) {
        state = {
          notifToggle,
          urgency: 35,
          lowEth,
        };
      }
      state.urgency = 35;
      await wallet.request({
        method: 'snap_manageState',
        params: ['update', state],
      });
      return urgency;
    }
    case 'set_urgency_60': {
      urgency = 60;
      let state: { notifToggle: boolean; urgency: number; lowEth: number };
      state = (await wallet.request({
        method: 'snap_manageState',
        params: ['get'],
      })) as { notifToggle: boolean; urgency: number; lowEth: number };
      if (!state) {
        state = {
          notifToggle,
          urgency: 60,
          lowEth,
        };
      }
      state.urgency = 60;
      await wallet.request({
        method: 'snap_manageState',
        params: ['update', state],
      });
      return urgency;
    }
    case 'set_urgency_90': {
      urgency = 90;
      let state: { notifToggle: boolean; urgency: number; lowEth: number };
      state = (await wallet.request({
        method: 'snap_manageState',
        params: ['get'],
      })) as { notifToggle: boolean; urgency: number; lowEth: number };
      if (!state) {
        state = {
          notifToggle,
          urgency: 90,
          lowEth,
        };
      }
      state.urgency = 90;
      await wallet.request({
        method: 'snap_manageState',
        params: ['update', state],
      });
      return urgency;
    }
    case 'set_urgency_100': {
      urgency = 100;
      let state: { notifToggle: boolean; urgency: number; lowEth: number };
      state = (await wallet.request({
        method: 'snap_manageState',
        params: ['get'],
      })) as { notifToggle: boolean; urgency: number; lowEth: number };
      if (!state) {
        state = {
          notifToggle,
          urgency: 100,
          lowEth,
        };
      }
      state.urgency = 100;
      await wallet.request({
        method: 'snap_manageState',
        params: ['update', state],
      });
      return urgency;
    }
    case 'call_api': {
      // get data from state whenever snap is invoked as snaps executions are ephemeral
      let state: { notifToggle: boolean; urgency: number; lowEth: number };
      state = (await wallet.request({
        method: 'snap_manageState',
        params: ['get'],
      })) as { notifToggle: boolean; urgency: number; lowEth: number };
      if (!state) {
        state = {
          notifToggle,
          urgency,
          lowEth,
        };
      }
      notifToggle = state.notifToggle;
      urgency = state.urgency;
      lowEth = state.lowEth;
      await wallet.request({
        method: 'snap_manageState',
        params: ['update', state],
      });
      console.log(
        `Called inside custom api call: notifToggle = ${notifToggle} and urgency = ${urgency}`,
      );
      const currentData = await fetch(CURRENT_DATA_ENDPOINT, {
        method: 'get',
        headers: {
          'Content-Type': 'application/json',
        },
      });
      const current = await currentData.json();
      if (Math.abs(current.speeds[0].baseFee - lowEth) < urgency / 38) {
        return wallet.request({
          method: 'snap_notify',
          params: [
            {
              type: 'native',
              message: `Gasfee is low! Pay now at ${current.speeds[0].baseFee} Gwei`,
            },
          ],
        });
      }
      return wallet.request({
        method: 'snap_notify',
        params: [
          {
            type: 'native',
            message: `Current gasfee is ${current.speeds[0].baseFee} Gwei`,
          },
        ],
      });
    }
    default: {
      throw new Error('Method not found.');
    }
  }
};

To calculate threshhold, we divided the urgency setting by 38 .After empirical testing with different values, 38 seemed to work best in most situations. There is a plan to fine tune and enhance this in the near future for more dynamic performance.

if (Math.abs(current.speeds[0].baseFee - lowEth) < urgency / 38) {
          return wallet.request({
            method: 'snap_notify',
            params: [
              {
                type: 'native',
                message: `Gasfee is low! Pay now at ${current.speeds[0].baseFee} Gwei`,
              },
            ],
          });
        }

As snap states are ephemeral, we needed to store state information (like notification on/off, urgency set by user) into storage using the snap storage API.


export const onRpcRequest: OnRpcRequestHandler = async ({
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  origin,
  request,
}) => {
  switch (request.method) {
    case 'notif_toggle_true': {
      console.log('Notification toggled to true');
      notifToggle = true; // toggle the notification
      console.log({ notifToggle });
      let state: { notifToggle: boolean; urgency: number; lowEth: number };
      state = (await wallet.request({
        method: 'snap_manageState',
        params: ['get'],
      })) as { notifToggle: boolean; urgency: number; lowEth: number };
      if (!state) {
        state = {
          notifToggle: true,
          urgency,
          lowEth,
        };
      }
      state.notifToggle = true;
      await wallet.request({
        method: 'snap_manageState',
        params: ['update', state],
      });
      return notifToggle;
    }
    case 'notif_toggle_false': {
      console.log('Notification toggled to false');
      notifToggle = false; // toggle the notification
      console.log({ notifToggle });
      let state: { notifToggle: boolean; urgency: number; lowEth: number };
      state = (await wallet.request({
        method: 'snap_manageState',
        params: ['get'],
      })) as { notifToggle: boolean; urgency: number; lowEth: number };
      if (!state) {
        state = {
          notifToggle: false,
          urgency,
          lowEth,
        };
      }
      state.notifToggle = false;
      await wallet.request({
        method: 'snap_manageState',
        params: ['update', state],
      });
      return notifToggle;
    }
     default: {
      throw new Error('Method not found.');
    }
  }
}; 

The Model

We then use a popular time series forecasting model called SARIMA or Seasonal ARIMA from the statsforecast package on the timeseries data to predict the lowest gas price expected in the next hour.


from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import requests
import numpy as np
from statsforecast.models import AutoARIMA
import json
def get_timeseries():
    with open('key.json') as f:
        data = json.load(f)
        print(data)
    key = data['key']
    history_data = requests.get(
        'https://api.owlracle.info/v3/eth/history?apikey={}&candles=100&txfee=true'
        .format(key))
    history_data = history_data.json()
    low = []
    for obj in history_data:
        low.append(obj['gasPrice']['low'])
    low.reverse()
    return np.array(low)
def get_prediction():
    values = get_timeseries()
    model = AutoARIMA()
    predictions = model.forecast(values, 2)
    print("Pred: ", predictions)
    prediction_json = {
        'low_30_minutes': predictions['mean'][0],
        'low_60_minutes': predictions['mean'][1]
    }
    return prediction_json
app = FastAPI()
origins = [
    "*",
]
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
@app.get("/")
async def root():
    pred = get_prediction()
    return pred

Why SARIMA?

  • A lot of literature on SARIMA for time-series forecasting in varying domains stated that the performance of SARIMA is good. We also referred to a study on ethereum gas price statistics, where they used SARIMA and obtained promising results.
  • An alternative would be deep learning techniques which usually involve larger models which also take more time to re-train hence making it less ideal for streaming data.
  • Some literatures we reffered:

Web Frontend

We used a simple React app as our web frontend interface. It contains the buttons for snap install, sending a dummy transaction, setting user urgency, toggling gas-price notifications and dark mode toggler. Its very simple and easy to use for any user.

HAmiesP

What are the next steps if you want to implement this?

There is a lot that can be done, we can start by making the model more reliable by tweaking the learning algorithm to make more robust predictions. Another area to improve is the urgency threshold where we need to come up with a more dynamic expression to handle wide variations of market profile, user urgency and transaction gas savings at the same time and quickly arrive at an almost optimal point where the user should make payment. Also we need to make the web interface a bit more user friendly and add some overall error handling at some corner cases which can occur rarely.

Can you tell us a little bit about yourself and your team?

We are a team consisting of eight BTech engineering students at IIT Patna. We formed the team to participate in Inter IIT Tech meet 11 (2023) where ConsenSys came up with a MetaMask Snaps problem statement.

Screenshot 2023-04-13 at 2.42.43 PM

  • Vaishakh: I am a final year Computer Science student at IIT Patna and I love my field of study. Lately, I’ve been participating in hackathons and I am thoroughly enjoying the experience. I can’t wait to explore more of the vast possibilities in Computer Science and see where it takes me in the future.
  • Aritra B. : Aritra is a Btech sophomore at AI and Data Science at Indian Institute of Technology, Patna and passionate about Blockchain and its applications in real world mass implementation. He has worked in a number of small blockchain projects before, which made the foundations for learning and exploring this domain. He is aimed at creating smart blockchain solutions using other domains of computer sciences like machine learning to create new innovations. He has been selected a KVPY fellow by the prestigious Indian Instiute of Science(IISC) in 2019 and is currently learning about ZK EVMs and it’s unique areas of implementations in this space.
  • Padmaksh: Pursuing BTech in Computer science and engineering at Indian institute of technology Patna and has a keen interest in cyber security. He’s also very much interested in problem solving and algorithmic puzzles. He’s further studying blockchain architecture and exploring other fields.
  • Kartikay: Undergrad at IIT Patna pursuing B.Tech in Mechanical Engineering currently in his 3rd year of course curriculum. He has a keen interest in web development and competitive programming. He has designed and developed multiple websites for many college clubs and fests. He has basic knowledge in Data Science and Web3.
  • Harsh: I am a sophomore year undergrad at IIT Patna pursuing Chemical Engineering. I am mostly into case studies and problem solving.
  • Dhushyanth: I am a final year Electrical Engineering student at IIT Patna, highly enthusiastic about technology and development. I’ve dabbled in a variety of fields like CRDT server implementation in rust to designing Perceptrons in Silicon Photonics. I like to have heated conversations about anything I can give my two cents about and thoroughly enjoy it!
  • Vishwas S: Vishwas is first year Computer Science student at IIT Patna who is passionate about his field of study and looking for opportunities to explore. Lately, he has developed a keen interest towards blockchain technology and working in it.
  • Ankur: I’m a sophomore undergrad at IIT Patna pursuing Electrical and Electronics Engineering. I recently developed a few websites for IIT Patna and enjoy problem solving. Lately I have been enjoying UI and UX with a knack for frontend. I like to studying human psychology and working towards building solutions to various problems

When were you first introduced to MetaMask Snaps and what was your experience like?

We got introduced to MetaMask Snaps first at Inter IIT Tech meet 2023. It’s a really unique and interesting add on to MetaMask, and can be used to bring endless customizations in the wallet. The development process is also pretty straightforward and we did not face any major setbacks while developing even though there was less documentation and discussion forum content available. Although it is still in development and lacks few important features as of now, we can already see the great potential it can have in upcoming years.

What makes MetaMask Snaps different from other wallets?

MetaMask Snaps is similar to an extension in a web browser. It is used to extend the functionalities of MetaMask. It is safe as the snaps are run in an isolated environment where they have access to a limited set of capabilities determined by the permissions granted by the user during installation. It is a great and safe way to customize your wallet experience.

Tell us about what building MetaMask Snaps is like for you and your team?

It’s one of the projects that allowed us to witness how different computer science fields could work together to solve a challenge. For my team and I, building this snap was a fantastic learning opportunity. We gained knowledge on how to implement our idea effectively as well as how to use machine learning to solve a problem on blockchain. Along the way, we also established a few new connections. On the other side, rest wallets feel quite restrictive for developers.

What does MetaMask Snaps mean to you?

Metamask Snaps add the features of extensions to a crypto wallet. It is really innovative and can be used for many critical use cases to improve mass adoption of cryptocurrency.

What opportunities do you see with MetaMask Snaps and the possibilities it unlocks for the Web3 space?

Metamask Snaps can really be a breakthrough in the web3 ecosystem as it transforms a simple Ethereum wallet to an entire web3 management tool where we can customize and enhance our web3 experience.

Any advice you would like to share with developers keen to try MetaMask Snaps?
Start reading the documentation. It is highly explanatory and can explain most of the use cases one can have. For any issue whose solution is not apparent, we would suggest asking them in the ConsenSys discord where there is a forum dedicated for this purpose.

To get started with MetaMask Snaps:

  1. Checkout the developer docs
  2. Install MetaMask Flask
  3. Check out a MetaMask Snaps guide
  4. Stay connected with us on Twitter, GitHub discussions, and Discord

Keep an eye out for our team at the next hackathon in an area near you! Happy BUIDLing ⚒️

Disclaimer: MetaMask Snaps are generally developed by third parties other the ConsenSys Software. Use of third-party-developed MetaMask Snaps is done at your own discretion and risk and with agreement that you will solely be responsible for any loss or damage that results from such activities. ConsenSys makes no express or implied warranty, whether oral or written, regarding any third-party-developed MetaMask Snaps and disclaims all liability for third-party developed Snaps. Use of blockchain-related software carries risks, and you assume them in full when using MetaMask Snaps.

MetaMask Grants DAO funds Spritely Foundation

https://metamask.io/news/developers/metamask-grants-dao-funds-spritely-foundation/

With 2023 full-steam ahead, we’re excited to announce our grant to the Spritely Foundation.

As a reminder, MetaMask Grants DAO was formed to support the developer community in building out impactful experiences within the MetaMask ecosystem. You can learn more about the employee-funded DAO and how to apply for a grant here.

Spritely: Re-Architecting Communication on the Internet

Spritely is a new model for the internet that aims to be both secure and collaborative, and is focused on secure social networking. The project is led by some very talented individuals, including Christine Lemmer-Webber and F. Randall (“Randy”) Farmer. Christine is known as a creator of the ActivityPub protocol (perhaps the most widely used decentralized social network protocol today), and Randy has been working on secure distributed applications since he helped build the first MMO (Lucasfilm’s Habitat).

Spritely builds the foundation for a maximally phishing-proof permissionless social network, where interactions are always rooted in consent and social introductions, making it harder for phishers to impersonate people, and easier for people to establish credibility and context-preserving social environments. We believe this is an ambitious and critical piece of infrastructure for allowing a safe permissionless web.

A Spritely application is not built on blockchains itself, but can interoperate with blockchains as needed for multi-party assurances. By default, users create their own programs, functions, and content and simply share access with each other over the network. Intermediary servers can provide replication, but they can always be routed around and are not necessary.

Since Spritely applications do not require financial buy-in the way blockchains do, it’s much friendlier to new user adoption, while still allowing a type of permissionless application to be built where it’s rooted in a user’s own sense of trust and safety. Their capability-security approach to permissionless computing makes a lot of sense to us at MetaMask, and we think tools like it can enable exciting kinds of applications.

As it is a true distributed object capability (ocap) system, the security model goes all the way down to the syntax of the language, which is chosen to ensure it’s as easy as possible to extend programs in a safe way.

This is similar to Agoric’s HardenedJS, which underpins the MetaMask Snaps system, which makes JavaScript secure through the ses-shim and the TC-39 standards process, and was a recent MetaMask grant recipient. While Agoric is oriented at making secure distributed programming maximally accessible to JavaScript programmers via the Endo project, Spritely has chosen the Scheme language (a Lisp dialect) which is less common but is more simple and flexible, and allows more open-ended experimentation and iteration for the platform. The two aspire to interoperate over a protocol called CapTP, in a joint project through the OCapN group.

Secure and Collaborative Internet Systems

The grant of $250k in USDC will primarily be used to port the Guile runtime for Scheme to WebAssembly. Guile is the Scheme environment that Spritely is built on, so this will allow the Spritely platform to be run anywhere that WebAssembly is available, like a browser, like within MetaMask. This will allow developers to use the Spritely framework to build decentralized applications that run in the browser and can be accessed by users via MetaMask or any other tool that supports WASM.

With the help of this grant, the Spritely community is confident that it will be able to make a significant impact in the world of secure and collaborative internet systems and MetaMask is proud to support this effort. You can learn more about the Spritely system in their document The Heart of Spritely.


If you’re a developer, take a look at our Snaps wish list here and apply for a grant to build out a thriving ecosystem with us.

We can’t guarantee when we will review your request or that it will get approved, but know that our team will review the application pipeline as often as we can. Thanks for being patient with us.

AA Snap: Democratizing Account Abstraction

https://metamask.io/news/developers/aa-snap-democratizing-account-abstraction/

MetaMask Snaps is the roadmap to making MetaMask the most extensible wallet in the world. As a developer, you can bring your features and APIs to MetaMask in totally new ways. Web3 developers are the core of this growth and this series aims to showcase the novel MetMask Snaps being built today.

AA Snap

Snap Repo: https://github.com/a42io/AAsnap

Why did you build it?

AA Snap is built for democratizing Account Abstraction (AA) for all developers and users. We believe AA will be widely used in the future. However, currently, it takes work for devs to integrate it with their dapps and for users to use it.

From devs’ perspective, it’s necessary to write additional code that supports AA in addition to EOA.

From users’ point of view, they cannot use their usual wallets, such as MetaMask, and need to install another wallet that supports AA, which is a bad UX.

Therefore, we wanted to make it easy to integrate and use AA by utilizing MetaMask Snaps.

Can you walk us through the technical implementation?

AA Snap is composed of three components: an example frontend, the MetaMask snap, and a temporary server. The snap enables devs and users to use an AA wallet (a contract wallet that supports EIP-4337) very easily. Please see the repository for the full implementation.

The example frontend

The example frontend is based on the template that is provided by MetaMask. It shows developers can easily integrate AA with their dapps by AA Snap.

For example, a balance of the AA wallet can be fetched with the simple code below.

const balance = (await window.ethereum.request({
    method: 'wallet_invokeSnap',
    params: [
        defaultSnapOrigin,
        {
            method: 'balance',
        },
    ],
})) as string;

To send a transaction from the AA wallet, you can just write the code below by passing a beneficiary address and value.

await window.ethereum.request({
    method: 'wallet_invokeSnap',
    params: [
        defaultSnapOrigin,
        {
            method: 'transfer',
            params: {
                to,        // beneficiary address
                value,     // value in ETH or MATIC
            },
        },
    ],
});

How easy is it to use the AA wallet from the user’s perspective? Try it here: https://AAsn.app

The Snap

The snap gets an instance of AA with the code below. To implement AA, we used the @account-abstraction/sdk npm package.

Since the AA wallet address can be deterministically derived from the user’s EOA, no user input is required.

export const getAbstractAccount = async (): Promise => {
    const provider = new ethers.providers.Web3Provider(wallet as any);
    await provider.send('eth_requestAccounts', []);
    const owner = provider.getSigner();
    const aa = new SimpleAccountAPI({
        provider,
        entryPointAddress,
        owner,
        factoryAddress,
    });
    return aa;
};

There are three steps to send a transaction from the AA wallet:

  1. The snap shows a confirmation within the MetaMask using the snap’s snap_confirm method. This process is not required but is needed for better UX because there’s no way for users to know the details of what they will sign.
  2. The code creates a user operation of the AA wallet and requests to sign a hash of the user operation. This process is almost the same as creating a tx from EOA and signing it.
  3. Send the signed user operation to a bundler via our server.
export const transfer = async (target: string, ethValue: string) => {
    const value = ethers.utils.parseEther(ethValue);
    const aa = await getAbstractAccount();
    const address = await aa.getAccountAddress();
    // 1. Show confirmation within MetaMask
    const result = await wallet.request({
        method: 'snap_confirm',
        params: [{
            prompt: 'Transfer',
            description: 'Transfer from your Abstraction Account',
            textAreaContent: `from: ${address}ntarget: ${target}nvalue: ${ethValue}`,
        }],
    });
    if (!result) {
        return;
    }
    // 2. Create a signed user operation of AA wallet
    const op = await aa.createSignedUserOp({
        target,
        value,
        data: '0x',
        maxFeePerGas,
        maxPriorityFeePerGas,
    });
    const printedOp = await printOp(op);
    const body = JSON.stringify({
        op: printedOp,
    });
    // 3. Send a signed user operation to the bundler
    const response = await fetch(SERVER_END_POINT {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body,
    });
};

The temporary server

During the hackathon, we encountered an error when calling the sendUserOpToBundler method inside the snap. Since we didn’t have time to dig into the issue, we decided to create a server to solve the problem temporarily. The temporary server just receives the signed user operation and passes it to a bundler.

Because of the error probably came from dependencies because there are some restrictions in the MetaMask Snaps execution environment. We think the temporary server can be removed by following this document: Patching Dependencies

app.post('/aa', async (req, res) => {
  const provider = new ethers.providers.JsonRpcProvider(
    process.env.RPC_ENDPOINT,
  );
  const client = await getHttpRpcClient(
    provider,
    process.env.BUNDLER_URL as string,
    process.env.ENTRY_POINT_ADDRESS as string,
  );
  try {
    const uoHash = await client.sendUserOpToBundler(JSON.parse(req.body.op));
    return res.json({
      uoHash,
    });
  } catch (e) {
    console.log(e);
    return res.status(400).send();
  }
});

What are the next steps if you would implement this?

We would like to remove unnecessary server-side code and run the snap alone. Also, currently, it is possible for the MetaMask Snaps developer like us to replace a transaction hash to be signed with a malicious one, so we would like to introduce or propose a mechanism to prevent it.

Can you tell us a little bit about yourself and your team?

team

Our team is running a small startup – a42 – in Japan and Singapore. a42 is building a Web3 smart lock “wΞlock” that enables auth with smart contracts including NFT and ENS: https://a42.io/w3lock
In 2022, we attended several hackathons to learn new technologies like MetaMask Snaps.

Hideyoshi Moriya (piyo.eth): Hideyoshi has been experimenting and building Ethereum based apps since 2017. He developed a collaborative NFT art project “Pixereum” in 2017. He worked at Google as a technical product specialist and started his company “a42” in 2019. In a42, he develops dapps that can work in the real world. He is currently developing a Web3 smart lock “wΞlock” that can be opened by ENS/NFT based on the PoC he developed in 2021: https://twitter.com/hm0429/status/1465241679800111107

Hiroyuki Tachibana (tachibana.eth): Hiroyuki is a co-founder and engineer at a42. He led a project to build a blockchain auth module for IoT devices “w3a.io” and received a grant from Ethereum Foundation. He received several prizes at ETHGlobal hackathons through 2022. He is currently developing a zkp privacy solution for the Web3 smart lock product.

Yusuke Moriya (yskmyskm.eth): Yusuke is a designer at a42. He worked as CG / VFX artist in various video productions and was involved in global brands to small-scale music videos. He has 12 years of experience in the film industry and specializes in abstract expressions using computer graphics. He has also worked as a cinematographer and documentary director.

What opportunities do you see with MetaMask Snaps and the possibilities it unlocks for the Web3 space?

We believe that MetaMask Snaps will make complex Web3 technologies easier for both developers and users and will significantly help traditional Web applications integrate with Web3. We are as excited about creating MetaMask Snaps as we were when the first mobile app store came out. We encourage you to give it a try and realize your ideas!

Any advice you would like to share with developers keen to try MetaMask Snaps?

We recommend starting with the MetaMask Snaps template (https://github.com/MetaMask/template-snap-monorepo) and modifying it first.

Tip: You may be wondering how to get the injected ethereum object. The wallet object is equivalent to it.

To get started with MetaMask Snaps:

  1. Checkout the developer docs
  2. Install MetaMask Flask
  3. Check out a MetaMask Snaps guide
  4. Stay connected with us on Twitter, GitHub discussions, and Discord

Keep an eye out for our team at the next hackathon in an area near you! Happy BUIDLing ⚒️

Disclaimer: MetaMask Snaps are generally developed by third parties other the ConsenSys Software. Use of third-party-developed MetaMask Snaps is done at your own discretion and risk and with agreement that you will solely be responsible for any loss or damage that results from such activities. ConsenSys makes no express or implied warranty, whether oral or written, regarding any third-party-developed MetaMask Snaps and disclaims all liability for third-party developed Snaps. Use of blockchain-related software carries risks, and you assume them in full when using MetaMask Snaps.

Polysnap: Invoking Polywrap Wasm Wrappers on the fly

https://metamask.io/news/developers/polysnap-invoking-polywrap-wasm-wrappers-on-the-fly/

MetaMask Snaps is the roadmap to making MetaMask the most extensible wallet in the world. As a developer, you can bring your features and APIs to MetaMask in totally new ways. Web3 developers are the core of this growth and this series aims to showcase the novel MetaMask Snaps being built today.

Polysnap

Snap Repo: https://github.com/Niraj-Kamdar/Polysnap

Why did you build it?

Currently, developers need to create a snap for every new capability they want to add to MetaMask. Polysnap presents a better approach to code-reuse. A wide selection of Polywrap-empowered Wasm modules are stored on IPFS. Polysnap lets app developers execute any Wasm wrapper deployed on IPFS, on the fly and securely, with a simple JSON RPC call, without needing to build a new Snap.

Users of a dapp relying on the Polysnap don’t need to install multiple snaps but only need to install polysnap which can help reduce potential attack vectors. Dapp using Polysnap can be more secure than traditional snap because Polysnap gatekeep any actions related to host capabilities like internet access, wallet access, etc and would always require user-confirmation before executing any code that relies on these capabilities.

Dapp developers don’t need to ask users to install multiple Snaps for them to run their app, but rather they can just use one Snap–Polysnap–and run any Polywrap wrappers.

Snap developers are no longer restricted to JavaScript and the JavaScript ecosystem for Snap development. They can instead write Polywrap wrappers in languages like Rust, Go, and AssemblyScript, and call the wrappers using Polysnap.

Can you walk us through the technical implementation?

The Polysnap project consists of two elements:

  1. Polysnap (MetaMask Snap)
  2. Polysnap Demo Website

The MetaMask Snap is the main feature, and the focus of the project. The website is used to demonstrate the Snap.

The Snap

Polysnap can be divided into 3 different parts.

  1. Polywrap Client
  2. Plugin Wrapper
  3. WASM Wrapper

1. Polywrap Client

Polywrap is building a unified execution environment for the internet that is safe, open, and user-owned.

Polywrap allows us to create endlessly extensible software that runs anywhere using a Polywrap Client. The Polywrap Client supports running two types of wrappers:

  1. Wasm Wrapper – any sandboxed Wasm wrapper module built and deployed on IPFS using the Polywrap toolchain
  2. Plugin Wrapper – any host capability wrapper that exposes different host functionalities like HTTP, the filesystem, and JSON-RPC, to Wasm wrappers.

You can check out how we are using the Polywrap Client to invoke any wrapper with a simple JSON-RPC call to the Polysnap.

export const onRpcRequest: OnRpcRequestHandler = async ({
  origin,
  request,
}) => {
  switch (request.method) {
    case 'wrap_invoke':
      const invocation = request.params as unknown as InvokerOptions;
      const isApproved = await wallet.request({
        method: 'snap_confirm',
        params: [
          {
            prompt: `${origin}`.substring(0, 40),
            description: `URI: ${invocation.uri}nMethod: ${invocation.method}`,
            textAreaContent: `Args ${JSON.stringify(invocation.args)}`,
          },
        ],
      });
      if (isApproved === true) {
        const client = await getClient();
        const response = await client.invoke(invocation);
        if (!response.ok) {
          throw response.error;
        }
        return deserializeMap(response.value);
      }
      throw new Error('User declined invocation');
    default:
      throw new Error('Method not found.');
  }
};

2. Plugin Wrapper

Plugin wrappers are directly embedded into Polysnap with the Polywrap Client. These Plugin wrappers expose the capabilities provided inside Metamask’s SES environement Ex: HTTP, Ethereum JSON-RPC

We have added support for three different plugins in this MVP.

  1. HTTP Plugin – exposes API that allows making HTTP GET/POST requests directly from the Wasm Wrapper
  2. IPFS Plugin – exposes API to store, pin and retrieve files from the IPFS
  3. IPFS URI Resolver Plugin – exposes API to resolve deployed Wasm Wrappers from the IPFS

3. Wasm Wrapper

Wasm wrappers are the Wasm modules built and deployed to IPFS using the Polywrap toolchain. Since Wasm is a sandboxed enviroment, it can’t perform any IO unless the host exposes an API to facilitate it. because of this, any Wasm wrappers can be securely run inside the MetaMask Snap. Polysnap can’t run any host functions, like accessing internet, without the help of Plugin wrappers. You can check out all of the IPFS deployed wrappers at: wrappers.io

export async function getClient(): Promise {
  const ipfsResolverWrapperResult = await ipfsResolverPlugin(
    {},
  ).createWrapper();
  // IPFS URI RESOLVER
  if (!ipfsResolverWrapperResult.ok) {
    throw ipfsResolverWrapperResult.error;
  }
  const ipfsUriResolver = new WrapperResolver(
    Uri.from('ens/ipfs-resolver.polywrap.eth'),
    ipfsResolverWrapperResult.value,
  );
  // IPFS RESOLVER
  const ipfsWrapperResult = await ipfsPlugin({}).createWrapper();
  if (!ipfsWrapperResult.ok) {
    throw ipfsWrapperResult.error;
  }
  const ipfsResolver = new WrapperResolver(
    Uri.from('ens/ipfs.polywrap.eth'),
    ipfsWrapperResult.value,
  );
  // HTTP RESOLVER
  const httpWrapperResult = await httpPlugin({}).createWrapper();
  if (!httpWrapperResult.ok) {
    throw httpWrapperResult.error;
  }
  const httpResolver = new WrapperResolver(
    Uri.from('ens/http.polywrap.eth'),
    httpWrapperResult.value,
  );
  // AGGREGATED RESOLVER
  const resolver = RecursiveResolver.from([
    httpResolver,
    ipfsResolver,
    ipfsUriResolver,
    new ExtendableUriResolver(),
  ]);
  return new PolywrapClient({
    interfaces: [
      {
        interface: new Uri('wrap://ens/uri-resolver.core.polywrap.eth'),
        implementations: [
          new Uri('wrap://ens/ipfs-resolver.polywrap.eth'),
        ],
      },
    ],
    envs: [
      {
        uri: new Uri('wrap://ens/ipfs.polywrap.eth'),
        env: {
          provider: defaultIpfsProviders[0],
          fallbackProviders: defaultIpfsProviders.slice(1),
        },
      },
    ],
    resolver,
  });
}

Polysnap Website

The Polysnap website is a simple demo site we created to showcase PolySnap in action. It has a button used to connect a MetaMask wallet and install the Snap, and a query dashboard that submits a JSON RPC call to the Polysnap and displays the result.

2Y2rfYy

To send an invocation to the Snap, a user provides three elements:

  • A uri that resolves to a Wasm wrapper (the hackathon project supports only IPFS URIs, but a future version could support ENS resolution as well)
  • The name of the method to invoke
  • A json object args that contains the arguments that will be passed to the invoked method

When the “Invoke” button is clicked, the website reads the values in these fields and forwards them to the Snap. The Snap opens a confirmation window to request approval of the invocation, ensuring the app does not make any invocations without the end-user’s consent.

invoke

If the invocation is approved, the Polywrap Client in the Snap handles the invocation and returns the result. The result is printed in a box below the buttons. Of course, in a real-world app, developers would typically set up invocations programmatically and use the result differently.

As its name suggests, Polysnap is one Snap with the power of many. With just Polysnap, developers can invoke any method in any Polywrap Wasm wrapper written in any Wasm-compilable language.

The wrappers are downloaded at runtime and cached. Since Wasm wrappers are sandboxed and stateless, Polysnap is adding an additional layer of security to the already-secure Snap environment.

And it’s all completely decentralized.

What are the next steps if you would implement this?

Here is the list of all the improvements that we envisioned for the next version of the Polysnap:

  • Enable support for more Plugin Wrappers such as: Cache, Concurrency, Ethereum, Near, Tezos, etc
  • Add permission-based security for access to each Polywrap plugin, ensuring that security can be managed by the end user.
  • Create a PolySnap installation website to showcase the Snap, host documentation, make installation easy for end-users
  • Add support for IPFS, ENS and HTTP Polywrap URI Resolvers
  • Support app developers submitting custom configurations for each invocation of the Polywrap Client configurable while invoking over JSON-RPC with MetaMask Snap
  • Support custom cache management solutions for wrappers cached by PolySnap

Can you tell us a little bit about yourself and your team?

We are both members of dOrg, a DAO of freelance software engineers and designers, and also developers at Polywrap.

  • Kris – I am a software engineer in Web3. My life was changed in 2020 when a friend introduced me to dOrg and the decentralized web. I soon joined the team at Polywrap to help build the next generation of SDK developer tools.
  • Niraj – I am a Web3 Developer at dOrg and currently working on the Polywrap project as a Core developer. I have been working as Web3 Developer for past 2 years and contributed to Badger, Opolis, Coordinape, and Llama before joining the Polywrap.

What opportunities do you see with MetaMask Snaps and the possibilities it unlocks for the Web3 space?

We think MetaMask Snaps has the potential to make MetaMask become a hub that will onboard millions of new users to web3. Both developer experience and security are paramount to the success of any plugin ecosystem. We believe that Polysnap can bring both to MetaMask Snaps by making it even more easy-to-use, extensible and secure.

Any advice you would like to share with developers keen to try MetaMask Snaps?

MetaMask Snaps allow extending capabilities of MetaMask by writing new extension MetaMask Snaps for your MetaMask wallet. So, it is a very powerful tool that can enable tons of use-cases like integrating different L1 wallets directly inside the MetaMask, Provide more insights for the transactions, etc. And we want to make Devx for enabling such use-cases even easier with Polysnap.

MetaMask Snaps are still new, but in just one weekend we saw teams build incredible MetaMask Snaps–even a Cosmos wallet that lives in MetaMask. Even if the MetaMask Snaps feature is still in a pre-production state, start early!

Or instead of writing a new Snap, you might consider writing a Polywrap Wasm wrapper in a language like Rust or AssemblyScript. You can then not only invoke it with Polysnap without having to write a new Snap of your own but also use it anywhere with the Polywrap client.

To get started with MetaMask Snaps:

  1. Checkout the developer docs
  2. Install MetaMask Flask
  3. Check out a MetaMask Snaps guide
  4. Stay connected with us on Twitter, GitHub discussions, and Discord

Keep an eye out for our team at the next hackathon in an area near you! Happy BUIDLing ⚒️

Disclaimer: MetaMask Snaps are generally developed by third parties other the ConsenSys Software. Use of third-party-developed MetaMask Snaps is done at your own discretion and risk and with agreement that you will solely be responsible for any loss or damage that results from such activities. ConsenSys makes no express or implied warranty, whether oral or written, regarding any third-party-developed Snaps and disclaims all liability for third-party developed MetaMask Snaps. Use of blockchain-related software carries risks, and you assume them in full when using MetaMask Snaps.