diff --git a/.snippets/code/builders/ethereum/precompiles/utility/eth-mainnet/sha3fips.sol b/.snippets/code/builders/ethereum/precompiles/utility/eth-mainnet/sha3fips.sol index 91aeff7c6..f308fabc5 100644 --- a/.snippets/code/builders/ethereum/precompiles/utility/eth-mainnet/sha3fips.sol +++ b/.snippets/code/builders/ethereum/precompiles/utility/eth-mainnet/sha3fips.sol @@ -1,4 +1,4 @@ -pragma solidity >=0.4.21; +pragma solidity ^0.7.0; contract Precompiles { function sha3fips(bytes memory data) public view returns (bytes32) { diff --git a/.snippets/code/builders/ethereum/precompiles/utility/nonspecific/RecoverPublicKey.sol b/.snippets/code/builders/ethereum/precompiles/utility/nonspecific/RecoverPublicKey.sol new file mode 100644 index 000000000..dddab5c67 --- /dev/null +++ b/.snippets/code/builders/ethereum/precompiles/utility/nonspecific/RecoverPublicKey.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.8.2 <0.9.0; + +contract RecoverPublicKey { + function recoverPublicKey( + bytes32 hash, + uint8 v, + bytes32 r, + bytes32 s + ) public view returns (bytes memory) { + address precompileAddress = 0x0000000000000000000000000000000000000402; + (bool success, bytes memory publicKey) = precompileAddress.staticcall( + abi.encodeWithSignature( + "ECRecoverPublicKey(bytes32,uint8,bytes32,bytes32)", + hash, + v, + r, + s + ) + ); + require(success, "ECRecoverPublicKey failed"); + return publicKey; + } +} diff --git a/.snippets/code/builders/ethereum/precompiles/utility/nonspecific/signMessage.js b/.snippets/code/builders/ethereum/precompiles/utility/nonspecific/signMessage.js new file mode 100644 index 000000000..044f45529 --- /dev/null +++ b/.snippets/code/builders/ethereum/precompiles/utility/nonspecific/signMessage.js @@ -0,0 +1,20 @@ +const { Web3 } = require('web3'); +const web3 = new Web3('https://rpc.api.moonbase.moonbeam.network'); + +// Address and private key +const address = 'INSERT_RECEIVER_ADDRESS'; +const pk1 = + 'INSERT_SENDER_PRIVATE_KEY'; +const msg = web3.utils.sha3('supercooltestmessage'); + +async function signMessage(pk) { + try { + // Sign and get signed message + const smsg = await web3.eth.accounts.sign(msg, pk); + console.log(smsg); + } catch (error) { + console.error(error); + } +} + +signMessage(pk1); diff --git a/.snippets/code/builders/ethereum/precompiles/utility/nonspecific/terminal/signature.md b/.snippets/code/builders/ethereum/precompiles/utility/nonspecific/terminal/signature.md new file mode 100644 index 000000000..94b0b79b3 --- /dev/null +++ b/.snippets/code/builders/ethereum/precompiles/utility/nonspecific/terminal/signature.md @@ -0,0 +1,12 @@ +
+ node signMessage.js + { + message: '0x5836e21a51f25aad199e2e0feb5ca19673ed56b3811285f5124d7a8171d75851', + messageHash: '0xa69b720d0293b9e8f4e471afb80f9d410b825abe5ce524e7d5755fd2a00bf9de', + v: '0x1b', + r: '0xb7d4783ee3b34d6fbc419d5b7bc67002c511322c5c71b49a7d78a8b7e9c5b30a', + s: '0x4e5939eaef3917b1cb09af9e632cc9a727b64191b7ee40a6ae34f6fdde60a371', + signature: '0xb7d4783ee3b34d6fbc419d5b7bc67002c511322c5c71b49a7d78a8b7e9c5b30a4e5939eaef3917b1cb09af9e632cc9a727b64191b7ee40a6ae34f6fdde60a3711b' + } + +
\ No newline at end of file diff --git a/.snippets/text/builders/ethereum/canonical-contracts/non-specific.md b/.snippets/text/builders/ethereum/canonical-contracts/non-specific.md index 943a457b5..0f335f7d5 100644 --- a/.snippets/text/builders/ethereum/canonical-contracts/non-specific.md +++ b/.snippets/text/builders/ethereum/canonical-contracts/non-specific.md @@ -3,21 +3,21 @@ === "Moonbeam" | Contract | Address | |:--------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:| - | [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 | - | [Dispatch](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_dispatch/struct.Dispatch.html){target=\_blank} | 0x0000000000000000000000000000000000000401 | + | [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 | + | Dispatch [Removed] | 0x0000000000000000000000000000000000000401 | | [ECRecoverPublicKey](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_simple/struct.ECRecoverPublicKey.html){target=\_blank} | 0x0000000000000000000000000000000000000402 | === "Moonriver" | Contract | Address | |:--------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:| - | [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 | - | [Dispatch](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_dispatch/struct.Dispatch.html){target=\_blank} | 0x0000000000000000000000000000000000000401 | + | [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 | + | Dispatch [Removed] | 0x0000000000000000000000000000000000000401 | | [ECRecoverPublicKey](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_simple/struct.ECRecoverPublicKey.html){target=\_blank} | 0x0000000000000000000000000000000000000402 | === "Moonbase Alpha" | Contract | Address | |:-------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:| - | [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 | - | [Dispatch](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_dispatch/struct.Dispatch.html){target=\_blank} | 0x0000000000000000000000000000000000000401 | + | [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 | + | Dispatch [Removed] | 0x0000000000000000000000000000000000000401 | | [ECRecoverPublicKey](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_simple/struct.ECRecoverPublicKey.html){target=\_blank} | 0x0000000000000000000000000000000000000402 | | [StorageCleaner](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_storage_cleaner/struct.StorageCleanerPrecompile.html){target=\_blank} | 0x0000000000000000000000000000000000000403 | diff --git a/builders/ethereum/precompiles/utility/.pages b/builders/ethereum/precompiles/utility/.pages index 6c257983f..0c6ccc106 100644 --- a/builders/ethereum/precompiles/utility/.pages +++ b/builders/ethereum/precompiles/utility/.pages @@ -3,4 +3,5 @@ nav: - index.md - 'Ethereum Native': 'eth-mainnet.md' - 'Precompile Registry': 'registry.md' - - 'Relay Data Verifier': 'relay-data-verifier.md' \ No newline at end of file + - 'Relay Data Verifier': 'relay-data-verifier.md' + - 'Non-Network Specific': 'non-specific.md' \ No newline at end of file diff --git a/builders/ethereum/precompiles/utility/eth-mainnet.md b/builders/ethereum/precompiles/utility/eth-mainnet.md index 02df02886..44eaca27e 100644 --- a/builders/ethereum/precompiles/utility/eth-mainnet.md +++ b/builders/ethereum/precompiles/utility/eth-mainnet.md @@ -1,16 +1,16 @@ --- title: Ethereum MainNet Precompiles -description: Learn how to use the standard precompiled contracts availble on Ethereum such as ECRECOVER, SHA256, and more on Moonbeam. -keywords: ethereum, moonbeam, ecrecover, sha256, sha3FIPS256, ripemd-160, Bn128Add, Bn128Mul, Bn128Pairing +description: Learn how to use the standard precompiled contracts available on Ethereum such as ECRECOVER, SHA256, and more on Moonbeam. +keywords: ethereum, moonbeam, ecrecover, sha256, ripemd-160, Bn128Add, Bn128Mul, Bn128Pairing --- # Ethereum MainNet Precompiled Contracts ## Introduction {: #introduction } -Precompiled contracts in Ethereum are contracts that include complex cryptographic computations, but do not require the overhead of the EVM. There are nine precompiles that can be used within the EVM that handle specific common operations such as hashing and signature schemes. +Precompiled contracts in Ethereum are contracts that include complex cryptographic computations, but do not require the overhead of the EVM. These precompiles can be used within the EVM to handle specific common operations such as hashing and signature schemes. -The following precompiles are currently included: ecrecover, sha256, sha3FIPS256, ripemd-160, Bn128Add, Bn128Mul, Bn128Pairing, the identity function, and modular exponentiation. +The following precompiles are currently included: ecrecover, sha256, ripemd-160, Bn128Add, Bn128Mul, Bn128Pairing, the identity function, and modular exponentiation. These precompiles are natively available on Ethereum and, to maintain Ethereum compatibility, they are also available on Moonbeam. @@ -70,18 +70,6 @@ This hashing function returns the SHA256 hash from the given data. To test this Once the contract is deployed, you can call the `checkHash()` method that returns **true** if the hash returned by `calculateHash()` is equal to the hash provided. -## Hashing with SHA3FIPS256 {: #hashing-with-sha3fips256 } - -SHA3-256 is part of the SHA-3 family of cryptographic hashes codified in [FIPS202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf) that produces an output 256 bits in length. Although the name is similar to SHA256, the SHA-3 family is built with an entirely different algorithm and accordingly produces a different hash output than SHA256 for the same input. You can verify this yourself using this [SHA3-256 Hash Calculator tool](https://md5calc.com/hash/sha3-256){target=\_blank}. After calculating the SHA3-256 output, change the algorithm in the drop-down selector to SHA256 and take note of the resulting output. - -Currently there is no SHA3-256 support in Solidity, so it needs to be called with inline assembly. The following sample code can be used to call this precompile. - -```solidity ---8<-- 'code/builders/ethereum/precompiles/utility/eth-mainnet/sha3fips.sol' -``` - -Using the [Remix compiler and deployment](/builders/ethereum/dev-env/remix/){target=\_blank} and with [MetaMask pointing to Moonbase Alpha](/tokens/connect/metamask/){target=\_blank}, you can deploy the contract and call the `sha3fips(bytes memory data)` method to return the encoded string of the data parameter. - ## Hashing with RIPEMD160 {: #hashing-with-ripemd-160 } This hashing function returns a RIPEMD160 hash from the given data. To test this precompile, you can use this [RIPEMD160 Hash Calculator tool](https://md5calc.com/hash/ripemd160){target=\_blank} to calculate the RIPEMD160 hash of any string. In this case, you'll do so again with `Hello World!`. You'll reuse the same code as before, but use the `ripemd160` function. Note that it returns a `bytes20` type variable: diff --git a/builders/ethereum/precompiles/utility/non-specific.md b/builders/ethereum/precompiles/utility/non-specific.md new file mode 100644 index 000000000..453019bab --- /dev/null +++ b/builders/ethereum/precompiles/utility/non-specific.md @@ -0,0 +1,103 @@ +--- +title: Non-Network Specific Precompiles +description: Learn how to use precompiled contracts, which are not specific to Ethereum or Moonbeam, yet are supported for use in your application. +keywords: ethereum, moonbeam, StorageCleaner, ECRecoverPublicKey, sha3FIPS256 +--- + +# Non-Network Specific Precompiled Smart Contracts + +## Introduction {: #introduction } + +A precompiled contract, or precompile, is a set of programmed functionalities hard-coded into the blockchain client. Precompiles perform computationally heavy tasks, such as cryptographic processes like hashing. Moving these functionalities to the blockchain client serves the dual purpose of making the computation more efficient than using a traditional smart contract and ensuring everyone has access to the complete and accurate set of processes and algorithms required to operate correctly. + +Precompile functionality is bundled and shared under a smart contract address, which allows interactions similar to those of a traditional smart contract. Some precompiled contracts are not specific to Ethereum or Moonbeam, but are supported for use in your Moonbeam application. + +The nonspecific precompiles currently included in this category include `StorageCleaner`, `ECRecoverPublicKey`, and `SHA3FIPS256`. + +In the next section, you will learn more about the functionalities included in these precompiles. + +## Clear Storage Entries with StorageCleaner {: #clear-storage-with-storagecleaner } + +The primary function of the `StorageCleaner` precompile is to clear storage entry key-value pairs for a smart contract marked as self-destructed, previously referred to as 'suicided.' `StorageCleaner` includes functionality to iterate over a list of addresses to identify self-destructed contracts and delete the appropriate storage entries associated with identified addresses. You can also input a numeric limit to prevent the precompile from consuming too much gas. + +With the implementation of [EIP-6780: SELFDESTRUCT](https://eips.ethereum.org/EIPS/eip-6780){target=\_blank} as part of the Ethereum Cancun/Dencun upgrade, contracts can only be self-destructed in the same transaction where they are created. This limitation keeps storage entries small and allows them to be automatically deleted during destruction. The `StorageCleaner` precompile remains available when a legacy contract needs storage entries cleared. + +## Retrieve a Public Key with ECRecoverPublicKey {: verifying-signatures-ecrecoverpublickey } + +The primary function of the `ECRecoverPublicKey` precompile is to recover the public key used to create a digital signature from a given message hash and signature. This precompile is similar to [ECRecover](/builders/ethereum/precompiles/utility/eth-mainnet/#verify-signatures-with-ecrecover/){target=\_blank}, with the exception of returning the public key of the account that signed the message rather than the account address. + +In the following sections, you will learn how to use the `ECRecoverPublicKey` precompile. + +### Checking Prerequisites {: checking-prerequisites } + +--8<-- 'text/_common/install-nodejs.md' + +The versions used in this example are v20.15.0 (Node.js) and 10.7.0 (npm). You will also need to install the [Web3](https://web3js.readthedocs.io/en/latest){target=\_blank} package by executing: + +```bash +npm install --save web3 +``` + +To verify the installed version of Web3, you can use the `ls` command: + +```bash +npm ls web3 +``` + +This example uses version 4.11.1. You will also use [Remix](/builders/ethereum/dev-env/remix/){target=\_blank}, connecting it to the Moonbase Alpha TestNet via [MetaMask](/tokens/connect/metamask/){target=\_blank}. + +--8<-- 'text/_common/endpoint-examples.md' + +### Retrieve Transaction Signature Values + +To use the `ECRecoverPublicKey` precompile, you must first sign a message to create and retrieve the message hash and transaction signature values (`v`, `r`, `s`) to pass as arguments in the contract call. Always use security best practices when handling private keys. + +Create a new file called `signMessage.js` in your project directory: + +```bash +touch signMessage.js +``` + +Open `signMessage.js` in your code editor and add the following script to initialize Web3 with Moonbase Alpha TestNet, sign and hash the message, and return the signature values: + +```js title="signMessage.js" +--8<-- 'code/builders/ethereum/precompiles/utility/nonspecific/signMessage.js' +``` + +Return to your terminal command line to run the script with this command: + +```bash +node signMessage.js +``` + +This code will return the following object in the terminal: + +--8<-- 'code/builders/ethereum/precompiles/utility/nonspecific/terminal/signature.md' + +Save these values as you will need them in the next section. + +### Test ECRecoverPublicKey Contract + +You can now visit [Remix](https://remix.ethereum.org/){target=\_blank} to test the precompiled contract. Note that you could also use the Web3.js library, but in this case, you can go to Remix to ensure it is using the precompiled contract on the blockchain. The Solidity code you can use to retrieve the public key is the following: + +```solidity title="RecoverPublicKey.sol" +--8<-- 'code/builders/ethereum/precompiles/utility/nonspecific/RecoverPublicKey.sol' +``` + +Using the [Remix compiler and deployment](/builders/ethereum/dev-env/remix/){target=\_blank} and with [MetaMask pointing to Moonbase Alpha](/tokens/connect/metamask/){target=\_blank}, you can deploy the contract and call the `recoverPublicKey()` method which returns the public key for the account that signed the message. You can now use this public key value for other cryptographic functions and verifications. + +![Returned Public Key on Remix](/images/builders/ethereum/precompiles/utility/nonspecific/nonspecific-1.webp) + +## Create a Hash with SHA3FIPS256 {: #create-a-hash-with-sha3fips256 } + +SHA3-256 is part of the SHA-3 family of cryptographic hashes codified in [FIPS202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf){target=\_blank} that produces an output 256 bits in length. Although the name is similar to SHA256, the SHA-3 family is built with an entirely different algorithm and accordingly produces a different hash output than SHA256 for the same input. You can verify this yourself using this [SHA3-256 Hash Calculator tool](https://md5calc.com/hash/sha3-256){target=\_blank}. After calculating the SHA3-256 output, change the algorithm in the drop-down selector to SHA256 and take note of the resulting output. + +Currently there is no SHA3-256 support in Solidity, so it needs to be called with inline assembly. The following sample code can be used to call this precompile. + +```solidity +--8<-- 'code/builders/ethereum/precompiles/utility/eth-mainnet/sha3fips.sol' +``` + +Using [Remix](/builders/ethereum/dev-env/remix/){target=\_blank} with [MetaMask pointing to Moonbase Alpha](/tokens/connect/metamask/){target=\_blank}, you can deploy the contract and call the `sha3fips(bytes memory data)` method to return the encoded string of the data parameter. + +--8<-- 'text/_disclaimers/third-party-content-intro.md' \ No newline at end of file diff --git a/images/builders/ethereum/precompiles/utility/nonspecific/nonspecific-1.webp b/images/builders/ethereum/precompiles/utility/nonspecific/nonspecific-1.webp new file mode 100644 index 000000000..d1d71dcb5 Binary files /dev/null and b/images/builders/ethereum/precompiles/utility/nonspecific/nonspecific-1.webp differ