Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port some Moonbeam precompiles #21

Merged
merged 3 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
563 changes: 508 additions & 55 deletions Cargo.lock

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]
members = [
"client/consensus/nimbus-consensus",
"precompiles/*",
"pallets/*",
"primitives/*",
"template/node",
Expand Down Expand Up @@ -36,6 +37,11 @@ schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backen
serde = { version = "1.0.101", default-features = false }
smallvec = "1.6.1"
tracing = "0.1.22"
num_enum = { version = "0.7.2", default-features = false }
paste = "1.0.14"
slices = "0.2.0"
libsecp256k1 = { version = "0.7.1", default-features = false }
sha3 = { version = "0.10.8", default-features = false }

# Crates.io (template only)
clap = { version = "4.0.9" }
Expand Down Expand Up @@ -96,6 +102,7 @@ sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "rel
sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0", default-features = false }
sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0", default-features = false }
sp-version = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0", default-features = false }
sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0", default-features = false }
substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0" }
sp-blockchain = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0", default-features = false }
sp-consensus = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0", default-features = false }
Expand Down Expand Up @@ -176,6 +183,9 @@ polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot-sd
staging-xcm = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0", default-features = false }
staging-xcm-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0", default-features = false }
staging-xcm-executor = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0", default-features = false }
xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0", default-features = false }
xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0", default-features = false }
xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0", default-features = false }

# Polkadot (client)
kusama-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0" }
Expand All @@ -187,7 +197,19 @@ rococo-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch =
westend-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0" }
xcm-simulator = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0" }

# Frontier (wasm)
fp-evm = { git = "https://github.com/paritytech/frontier", branch = "polkadot-v1.3.0", default-features = false }
pallet-evm = { git = "https://github.com/paritytech/frontier", branch = "polkadot-v1.3.0", default-features = false }
precompile-utils = { git = "https://github.com/paritytech/frontier", branch = "polkadot-v1.3.0", default-features = false }

# EVM
evm = { version = "0.41.1", default-features = false }

# Local (wasm)
pallet-evm-precompile-balances-erc20 = { path = "precompiles/balances-erc20", default-features = false }
pallet-evm-precompile-batch = { path = "precompiles/batch", default-features = false }
pallet-evm-precompile-call-permit = { path = "precompiles/call-permit", default-features = false }
pallet-evm-precompile-xcm-utils = { path = "precompiles/xcm-utils", default-features = false }
async-backing-primitives = { path = "primitives/async-backing", default-features = false }
pallet-author-inherent = { path = "pallets/author-inherent", default-features = false }
pallet-author-mapping = { path = "pallets/author-mapping", default-features = false }
Expand Down
59 changes: 59 additions & 0 deletions precompiles/balances-erc20/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
[package]
name = "pallet-evm-precompile-balances-erc20"
authors = { workspace = true }
description = "A Precompile to expose a Balances pallet through an ERC20-compliant interface."
edition = "2021"
version = "0.1.0"

[dependencies]
log = { workspace = true }
num_enum = { workspace = true }
paste = { workspace = true }
slices = { workspace = true }

# Moonbeam
precompile-utils = { workspace = true }

# Substrate
frame-support = { workspace = true }
frame-system = { workspace = true }
pallet-balances = { workspace = true }
pallet-timestamp = { workspace = true }
parity-scale-codec = { workspace = true, features = [ "max-encoded-len" ] }
sp-core = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }
sp-std = { workspace = true }

# Frontier
fp-evm = { workspace = true }
pallet-evm = { workspace = true, features = [ "forbid-evm-reentrancy" ] }

[dev-dependencies]
derive_more = { workspace = true }
hex-literal = { workspace = true }
libsecp256k1 = { workspace = true }
serde = { workspace = true }
sha3 = { workspace = true }

# Moonbeam
precompile-utils = { workspace = true, features = [ "std", "testing" ] }

pallet-timestamp = { workspace = true, features = [ "std" ] }
scale-info = { workspace = true, features = [ "derive" ] }
sp-runtime = { workspace = true, features = [ "std" ] }

[features]
default = [ "std" ]
std = [
"fp-evm/std",
"frame-support/std",
"frame-system/std",
"pallet-balances/std",
"pallet-evm/std",
"parity-scale-codec/std",
"precompile-utils/std",
"sp-core/std",
"sp-io/std",
"sp-std/std",
]
123 changes: 123 additions & 0 deletions precompiles/balances-erc20/ERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.8.3;

/// @dev The IERC20 contract's address.
address constant IERC20_ADDRESS = 0x0000000000000000000000000000000000000802;
girazoki marked this conversation as resolved.
Show resolved Hide resolved

/// @dev The IERC20 contract's instance.
IERC20 constant IERC20_CONTRACT = IERC20(IERC20_ADDRESS);

/// @title ERC20 interface
/// @dev see https://github.com/ethereum/EIPs/issues/20
/// @dev copied from https://github.com/OpenZeppelin/openzeppelin-contracts
/// @custom:address 0x0000000000000000000000000000000000000802
interface IERC20 {
/// @dev Returns the name of the token.
/// @custom:selector 06fdde03
function name() external view returns (string memory);

/// @dev Returns the symbol of the token.
/// @custom:selector 95d89b41
function symbol() external view returns (string memory);

/// @dev Returns the decimals places of the token.
/// @custom:selector 313ce567
function decimals() external view returns (uint8);

/// @dev Total number of tokens in existence
/// @custom:selector 18160ddd
function totalSupply() external view returns (uint256);

/// @dev Gets the balance of the specified address.
/// @custom:selector 70a08231
/// @param owner The address to query the balance of.
/// @return An uint256 representing the amount owned by the passed address.
function balanceOf(address owner) external view returns (uint256);

/// @dev Function to check the amount of tokens that an owner allowed to a spender.
/// @custom:selector dd62ed3e
/// @param owner address The address which owns the funds.
/// @param spender address The address which will spend the funds.
/// @return A uint256 specifying the amount of tokens still available for the spender.
function allowance(address owner, address spender)
external
view
returns (uint256);

/// @dev Transfer token for a specified address
/// @custom:selector a9059cbb
/// @param to The address to transfer to.
/// @param value The amount to be transferred.
/// @return true if the transfer was succesful, revert otherwise.
function transfer(address to, uint256 value) external returns (bool);

/// @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
/// Beware that changing an allowance with this method brings the risk that someone may use both the old
/// and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
/// race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
/// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
/// @custom:selector 095ea7b3
/// @param spender The address which will spend the funds.
/// @param value The amount of tokens to be spent.
/// @return true, this cannot fail
function approve(address spender, uint256 value) external returns (bool);

/// @dev Transfer tokens from one address to another
/// @custom:selector 23b872dd
/// @param from address The address which you want to send tokens from
/// @param to address The address which you want to transfer to
/// @param value uint256 the amount of tokens to be transferred
/// @return true if the transfer was succesful, revert otherwise.
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);

/// @dev Event emited when a transfer has been performed.
/// @custom:selector ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
/// @param from address The address sending the tokens
/// @param to address The address receiving the tokens.
/// @param value uint256 The amount of tokens transfered.
event Transfer(address indexed from, address indexed to, uint256 value);

/// @dev Event emited when an approval has been registered.
/// @custom:selector 8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925
/// @param owner address Owner of the tokens.
/// @param spender address Allowed spender.
/// @param value uint256 Amount of tokens approved.
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}

/// @title Native currency wrapper interface.
/// @dev Allow compatibility with dApps expecting this precompile to be
/// a WETH-like contract.
/// Moonbase address : 0x0000000000000000000000000000000000000802
interface WrappedNativeCurrency {
/// @dev Provide compatibility for contracts that expect wETH design.
/// Returns funds to sender as this precompile tokens and the native tokens are the same.
/// @custom:selector d0e30db0
function deposit() external payable;

/// @dev Provide compatibility for contracts that expect wETH design.
/// Does nothing.
/// @custom:selector 2e1a7d4d
/// @param value uint256 The amount to withdraw/unwrap.
function withdraw(uint256 value) external;

/// @dev Event emited when deposit() has been called.
/// @custom:selector e1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c
/// @param owner address Owner of the tokens
/// @param value uint256 The amount of tokens "wrapped".
event Deposit(address indexed owner, uint256 value);

/// @dev Event emited when withdraw(uint256) has been called.
/// @custom:selector 7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65
/// @param owner address Owner of the tokens
/// @param value uint256 The amount of tokens "unwrapped".
event Withdrawal(address indexed owner, uint256 value);
}
39 changes: 39 additions & 0 deletions precompiles/balances-erc20/Permit.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.8.3;

/// @author The Moonbeam Team
/// @title Extension of the ERC20 interface that allows users to
/// @dev Sign permit messages to interact with contracts without needing to
/// make a first approve transaction.
interface Permit {
/// @dev Consumes an approval permit.
/// Anyone can call this function for a permit.
/// @custom:selector d505accf
/// @param owner Owner of the tokens issuing the permit
/// @param spender Address whose allowance will be increased.
/// @param value Allowed value.
/// @param deadline Timestamp after which the permit will no longer be valid.
/// @param v V component of the signature.
/// @param r R component of the signature.
/// @param s S component of the signature.
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;

/// @dev Returns the current nonce for given owner.
/// A permit must have this nonce to be consumed, which will
/// increase the nonce by one.
/// @custom:selector 7ecebe00
function nonces(address owner) external view returns (uint256);

/// @dev Returns the EIP712 domain separator. It is used to avoid replay
/// attacks accross assets or other similar EIP712 message structures.
/// @custom:selector 3644e515
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
Loading
Loading