Skip to content

Commit

Permalink
build erc1155 skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
programskillforverification committed Sep 4, 2024
1 parent d4f57e6 commit c24e0bd
Show file tree
Hide file tree
Showing 14 changed files with 284 additions and 1 deletion.
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ members = [
"examples/basic/token",
"examples/basic/script",
"examples/ecdsa",
"benches",
"benches", "examples/erc1155",
]
default-members = [
"contracts",
Expand Down
5 changes: 5 additions & 0 deletions contracts/src/token/erc1155/extensions/burnable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use crate::token::erc1155::Erc1155;

/// Extension of [`Erc1155`] that allows token holders to destroy both their
/// own tokens and those that they have been approved to use.
pub trait IErc1155Burnable {}
4 changes: 4 additions & 0 deletions contracts/src/token/erc1155/extensions/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//! Common extensions to the ERC-1155 standard.
pub mod burnable;
pub mod supply;
pub mod uri_storage;
Empty file.
Empty file.
193 changes: 193 additions & 0 deletions contracts/src/token/erc1155/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
//! Implementation of the [`Erc1155`] token standard.

use stylus_sdk::{alloy_sol_types::sol, call::MethodError, prelude::*};

pub mod extensions;

sol! {
/// Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.
#[allow(missing_docs)]
event TransferSingle(
address indexed operator,
address indexed from,
address indexed to,
uint256 id,
uint256 value
);

/// Equivalent to multiple {TransferSingle} events, where `operator`.
/// `from` and `to` are the same for all transfers.
#[allow(missing_docs)]
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);

/// Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
/// `approved`.
#[allow(missing_docs)]
event ApprovalForAll(address indexed account, address indexed operator, bool approved);

/// Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
///
/// If an {URI} event was emitted for `id`, the [standard]
/// (https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees]) that `value` will equal the value
/// returned by [`IERC1155MetadataURI-uri`].
#[allow(missing_docs)]
event URI(string value, uint256 indexed id);
}

sol! {
/// Indicates an error related to the current `balance` of a `sender`. Used
/// in transfers.
///
/// * `sender` - Address whose tokens are being transferred.
/// * `balance` - Current balance for the interacting account.
/// * `needed` - Minimum amount required to perform a transfer.
/// * `tokenId` - Identifier number of a token.
#[derive(Debug)]
#[allow(missing_docs)]
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

/// Indicates a failure with the token `sender`. Used in transfers.
///
/// * `sender` - Address whose tokens are being transferred.
#[derive(Debug)]
#[allow(missing_docs)]
error ERC1155InvalidSender(address sender);

/// Indicates a failure with the token `receiver`. Used in transfers.
///
/// * `receiver` - Address to which tokens are being transferred.
#[derive(Debug)]
#[allow(missing_docs)]
error ERC1155InvalidReceiver(address receiver);

/// Indicates a failure with the `operator`’s approval. Used
/// in transfers.
///
/// * `operator` - Address that may be allowed to operate on tokens without being their owner.
/// * `owner` - Address of the current owner of a token.
#[derive(Debug)]
#[allow(missing_docs)]
error ERC1155MissingApprovalForAll(address operator, address owner);

/// Indicates a failure with the `approver` of a token to be approved. Used
/// in approvals.
///
/// * `approver` - Address initiating an approval operation.
#[derive(Debug)]
#[allow(missing_docs)]
error ERC1155InvalidApprover(address approver);

/// Indicates a failure with the `operator` to be approved. Used
/// in approvals.
///
/// * `operator` - Address that may be allowed to operate on tokens without being their owner.
#[derive(Debug)]
#[allow(missing_docs)]
error ERC1155InvalidOperator(address operator);

/// Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
/// Used in batch transfers.
///
/// * `idsLength` - Length of the array of token identifiers.
/// * `valuesLength` - Length of the array of token amounts.
#[derive(Debug)]
#[allow(missing_docs)]
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

/// An [`Erc1155`] error defined as described in [ERC-6093].
///
/// [ERC-6093]: https://eips.ethereum.org/EIPS/eip-6093
#[derive(SolidityError, Debug)]
pub enum Error {
/// Indicates an error related to the current `balance` of `sender`. Used
/// in transfers.
InsufficientBalance(ERC1155InsufficientBalance),
/// Indicates a failure with the token `sender`. Used in transfers.
InvalidSender(ERC1155InvalidSender),
/// Indicates a failure with the token `receiver`. Used in transfers.
InvalidReceiver(ERC1155InvalidReceiver),
/// Indicates a failure with the `operator`’s approval. Used in transfers.
MissingApprovalForAll(ERC1155MissingApprovalForAll),
/// Indicates a failure with the `approver` of a token to be approved. Used
/// in approvals.
InvalidApprover(ERC1155InvalidApprover),
/// Indicates a failure with the `operator` to be approved. Used in
/// approvals.
InvalidOperator(ERC1155InvalidOperator),
/// Indicates an array length mismatch between ids and values in a
/// safeBatchTransferFrom operation. Used in batch transfers.
InvalidArrayLength(ERC1155InvalidArrayLength),
}

impl MethodError for Error {
fn encode(self) -> alloc::vec::Vec<u8> {
self.into()
}
}

sol_interface! {
interface IERC1155Receiver {

/// Handles the receipt of a single ERC-1155 token type. This function is
/// called at the end of a `safeTransferFrom` after the balance has been updated.
///
/// NOTE: To accept the transfer, this must return
/// `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
/// (i.e. 0xf23a6e61, or its own function selector).
///
/// * `operator` - The address which initiated the transfer (i.e. msg.sender)
/// * `from` - The address which previously owned the token
/// * `id` - The ID of the token being transferred
/// * `value` - The amount of tokens being transferred
/// * `data` - Additional data with no specified format
/// Return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
#[allow(missing_docs)]
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);

/// Handles the receipt of a multiple ERC-1155 token types. This function
/// is called at the end of a `safeBatchTransferFrom` after the balances have
/// been updated.
///
/// NOTE: To accept the transfer(s), this must return
/// `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
/// (i.e. 0xbc197c81, or its own function selector).
///
/// * `operator` - The address which initiated the batch transfer (i.e. msg.sender)
/// * `from` - The address which previously owned the token
/// * `ids` - An array containing ids of each token being transferred (order and length must match values array)
/// * `values` - An array containing amounts of each token being transferred (order and length must match ids array)
/// * `data` - Additional data with no specified format
/// * Return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
#[allow(missing_docs)]
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
}

sol_storage! {
/// State of an [`Erc1155`] token.
pub struct Erc1155 {
/// Maps users to balances.
mapping(uint256 => mapping(address => uint256)) _balances;
/// Maps owners to a mapping of operator approvals.
mapping(address => mapping(address => bool)) _operator_approvals;
}
}
1 change: 1 addition & 0 deletions contracts/src/token/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! Token standards.
pub mod erc1155;
pub mod erc20;
pub mod erc721;
17 changes: 17 additions & 0 deletions examples/erc1155/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "erc1155-example"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
license.workspace = true
keywords.workspace = true
repository.workspace = true

[dependencies]
openzeppelin-stylus = { path = "../../contracts" }

[dev-dependencies]
e2e = { path = "../../lib/e2e" }

[lints]
workspace = true
7 changes: 7 additions & 0 deletions examples/erc1155/src/ERC1155ReceiverMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.21;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.2/contracts/token/ERC1155/IERC1155Receiver.sol";

contract IERC1155ReceiverMock is IERC1155Receiver {}
13 changes: 13 additions & 0 deletions examples/erc1155/src/constructor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

contract Erc1155Example {
mapping(address => mapping(uint256 => uint256)) private _balanceOf;
mapping(address => mapping(address => bool)) private _isApprovedForAll;

bool _paused;

constructor() {
_paused = false;
}
}
14 changes: 14 additions & 0 deletions examples/erc1155/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pub fn add(left: u64, right: u64) -> u64 {
left + right
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}
9 changes: 9 additions & 0 deletions examples/erc1155/tests/abi/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#![allow(dead_code)]
use alloy::sol;

sol!(
#[sol(rpc)]
contract Erc1155 {

}
);
12 changes: 12 additions & 0 deletions examples/erc1155/tests/erc1155.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#![cfg(feature = "e2e")]

use abi::Erc1155;

mod abi;

// ============================================================================
// Integration Tests: ERC-1155 Token Standard
// ============================================================================

#[e2e::test]
async fn constructs(alice: Account) -> eyre::Result<()> {}

0 comments on commit c24e0bd

Please sign in to comment.