Skip to content

Commit

Permalink
Port some Moonbeam precompiles (#21)
Browse files Browse the repository at this point in the history
* Port Moonbeam precompiles

# Conflicts:
#	Cargo.toml

* remove hardcoded addresses

* remove custom dev comment with addresses

---------

Co-authored-by: girazoki <gorka.irazoki@gmail.com>
  • Loading branch information
fgamundi and girazoki authored Feb 14, 2024
1 parent 3fb7691 commit 70bec1a
Show file tree
Hide file tree
Showing 25 changed files with 7,173 additions and 55 deletions.
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",
]
116 changes: 116 additions & 0 deletions precompiles/balances-erc20/ERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.8.3;

/// @title ERC20 interface
/// @dev see https://github.com/ethereum/EIPs/issues/20
/// @dev copied from https://github.com/OpenZeppelin/openzeppelin-contracts
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

0 comments on commit 70bec1a

Please sign in to comment.