Skip to Content
EVMPointer ContractsERC1155 Pointer Contracts

ERC1155 Pointer Contracts

ERC1155 pointer contracts extend Sei’s interoperability framework to support multi-token standards. They allow interaction between ERC1155 contracts and their Cosmos equivalents. This supports use cases for gaming, collectibles, and complex token economies.

Overview

The ERC1155 standard allows a single contract to manage multiple token types - both fungible and non-fungible tokens. ERC1155 pointers maintain this flexibility while providing cross-environment functionality.

Key Features

  • Multi-Token Support: Bridge multiple token types in a single pointer contract
  • Batch Operations: Efficient batch transfers and operations
  • Flexible Token Types: Support for both fungible and non-fungible tokens
  • Gas Optimization: Reduced gas costs for complex multi-token operations
  • Cross-Environment Compatibility: Direct interaction between Cosmos and EVM

Prerequisites

Before deploying ERC1155 pointers, ensure you have:

Checking Existing Pointers

Always verify if a pointer already exists for your ERC1155 contract:

seid q evm pointer ERC1155 [CONTRACT_ADDRESS] --node=https://rpc.sei-apis.com

Example:

seid q evm pointer ERC1155 0x1234567890abcdef1234567890abcdef12345678 --node=https://rpc.sei-apis.com

ERC1155 Pointer Registration

⚠️

Important: CW→ERC registration is disabled for security reasons. Only ERC→CW registration is currently supported.

ERC1155 → CosmWasm Pointer

To create a CosmWasm pointer for an existing ERC1155 contract:

seid tx evm register-pointer ERC1155 $ERC1155_CONTRACT_ADDRESS \ --from=$SENDER \ --chain-id=pacific-1 \ --broadcast-mode=block \ --gas=300000 \ --fees=10000usei \ --node=https://rpc.sei-apis.com

Parameters

  • ERC1155_CONTRACT_ADDRESS: The address of the ERC1155 contract
  • --from: Your wallet/key name
  • --chain-id: Network identifier (pacific-1 for mainnet, atlantic-2 for testnet)
  • --gas: Gas limit (ERC1155 operations may require more gas)
  • --fees: Transaction fees in usei

Example Registration

# Set environment variables export ERC1155_ADDRESS="0xabcdef1234567890abcdef1234567890abcdef12" export SENDER="my-wallet" # Register the pointer seid tx evm register-pointer ERC1155 $ERC1155_ADDRESS \ --from=$SENDER \ --chain-id=pacific-1 \ --broadcast-mode=block \ --gas=350000 \ --fees=12000usei \ --node=https://rpc.sei-apis.com

Verification

After registration, confirm the pointer was created successfully:

seid q evm pointer ERC1155 $ERC1155_ADDRESS --node=https://rpc.sei-apis.com

ERC1155 Pointer Usage

Solidity Integration

pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; contract ERC1155PointerExample is ERC1155Holder { IERC1155 public immutable erc1155Contract; constructor(address _erc1155Address) { erc1155Contract = IERC1155(_erc1155Address); } // Batch transfer multiple token types function batchTransferToPointer( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) external { erc1155Contract.safeBatchTransferFrom( msg.sender, to, ids, amounts, data ); } // Check balance of specific token ID function getTokenBalance(address account, uint256 tokenId) external view returns (uint256) { return erc1155Contract.balanceOf(account, tokenId); } // Check multiple token balances function getBatchBalances( address[] memory accounts, uint256[] memory ids ) external view returns (uint256[] memory) { return erc1155Contract.balanceOfBatch(accounts, ids); } }

CosmWasm Integration

use cosmwasm_std::{ Addr, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, Uint128, }; use cw1155::{Cw1155ExecuteMsg, Cw1155QueryMsg, TokensResponse}; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct InstantiateMsg { pub erc1155_pointer: Addr, } // Execute message to interact with ERC1155 pointer pub fn execute_transfer_batch( deps: DepsMut, env: Env, info: MessageInfo, to: Addr, token_ids: Vec<String>, amounts: Vec<Uint128>, ) -> Result<Response, ContractError> { let erc1155_pointer = ERC1155_POINTER.load(deps.storage)?; let transfer_msg = Cw1155ExecuteMsg::SendBatch { from: Some(info.sender.to_string()), to: to.to_string(), batch: token_ids.into_iter().zip(amounts.into_iter()) .map(|(id, amount)| (id, amount, None)) .collect(), msg: None, }; let cosmos_msg = CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: erc1155_pointer.to_string(), msg: to_binary(&transfer_msg)?, funds: vec![], }); Ok(Response::new() .add_message(cosmos_msg) .add_attribute("action", "batch_transfer") .add_attribute("to", to)) }

Advanced Use Cases

Gaming Assets Bridge

contract GameAssetsBridge { IERC1155 public gameAssets; mapping(uint256 => string) public assetTypes; // Token ID ranges uint256 constant WEAPONS_START = 1; uint256 constant ARMOR_START = 10000; uint256 constant CONSUMABLES_START = 20000; constructor(address _gameAssets) { gameAssets = IERC1155(_gameAssets); } function bridgeGameAssets( address player, uint256[] memory tokenIds, uint256[] memory amounts ) external { // Validate token types for (uint256 i = 0; i < tokenIds.length; i++) { require(isValidGameAsset(tokenIds[i]), "Invalid game asset"); } // Transfer to bridge gameAssets.safeBatchTransferFrom( player, address(this), tokenIds, amounts, "" ); // Emit bridge event for off-chain processing emit AssetsBridged(player, tokenIds, amounts); } function isValidGameAsset(uint256 tokenId) internal pure returns (bool) { return tokenId >= WEAPONS_START; } }

Multi-Token Marketplace

contract MultiTokenMarketplace { struct Listing { address seller; address tokenContract; uint256 tokenId; uint256 amount; uint256 pricePerToken; bool active; } mapping(bytes32 => Listing) public listings; function createListing( address tokenContract, uint256 tokenId, uint256 amount, uint256 pricePerToken ) external { bytes32 listingId = keccak256( abi.encodePacked(msg.sender, tokenContract, tokenId, block.timestamp) ); // Transfer tokens to marketplace IERC1155(tokenContract).safeTransferFrom( msg.sender, address(this), tokenId, amount, "" ); listings[listingId] = Listing({ seller: msg.sender, tokenContract: tokenContract, tokenId: tokenId, amount: amount, pricePerToken: pricePerToken, active: true }); emit ListingCreated(listingId, msg.sender, tokenContract, tokenId); } function purchaseTokens(bytes32 listingId, uint256 amount) external payable { Listing storage listing = listings[listingId]; require(listing.active, "Listing not active"); require(amount <= listing.amount, "Insufficient tokens"); uint256 totalPrice = amount * listing.pricePerToken; require(msg.value >= totalPrice, "Insufficient payment"); // Transfer tokens to buyer IERC1155(listing.tokenContract).safeTransferFrom( address(this), msg.sender, listing.tokenId, amount, "" ); // Update listing listing.amount -= amount; if (listing.amount == 0) { listing.active = false; } // Transfer payment to seller payable(listing.seller).transfer(totalPrice); // Refund excess payment if (msg.value > totalPrice) { payable(msg.sender).transfer(msg.value - totalPrice); } } }

Gas Considerations

ERC1155 operations, especially batch operations, may require higher gas limits:

OperationEstimated GasUse Case
Single Transfer~45,000Basic token transfer
Batch Transfer (5 tokens)~120,000Multi-token operations
Pointer Registration~300,000Initial setup
Complex Multi-Token Operations~500,000+Gaming marketplaces

Gas Optimization Tips

contract OptimizedERC1155Operations { // Use packed structs for batch operations struct BatchTransfer { uint128 tokenId; uint128 amount; } function optimizedBatchTransfer( address to, BatchTransfer[] calldata transfers ) external { uint256 length = transfers.length; uint256[] memory ids = new uint256[](length); uint256[] memory amounts = new uint256[](length); // Unpack in a single loop for (uint256 i = 0; i < length;) { ids[i] = transfers[i].tokenId; amounts[i] = transfers[i].amount; unchecked { ++i; } } IERC1155(tokenContract).safeBatchTransferFrom( msg.sender, to, ids, amounts, "" ); } }

Security Considerations

⚠️

Security: Always validate token IDs and amounts in multi-token operations to prevent unauthorized transfers.

Input Validation

contract SecureERC1155Bridge { mapping(uint256 => bool) public allowedTokenIds; uint256 public maxBatchSize = 100; modifier validBatch(uint256[] memory ids, uint256[] memory amounts) { require(ids.length == amounts.length, "Array length mismatch"); require(ids.length <= maxBatchSize, "Batch too large"); for (uint256 i = 0; i < ids.length; i++) { require(allowedTokenIds[ids[i]], "Token not allowed"); require(amounts[i] > 0, "Invalid amount"); } _; } function secureBatchTransfer( address to, uint256[] memory ids, uint256[] memory amounts ) external validBatch(ids, amounts) { // Safe to proceed with transfer IERC1155(tokenContract).safeBatchTransferFrom( msg.sender, to, ids, amounts, "" ); } }

Troubleshooting

Common Issues

Registration Fails

# Check if pointer already exists seid q evm pointer ERC1155 $CONTRACT_ADDRESS # Verify contract exists and is ERC1155 # Check gas limits and fees

Transfer Failures

  • Verify token ownership and approvals
  • Check for sufficient gas limits
  • Ensure contract implements ERC1155Receiver if receiving
  • Validate token IDs exist in the contract

Performance Issues

  • Use batch operations when possible
  • Implement pagination for large datasets
  • Cache frequently accessed data
  • Optimize struct packing

Debug Commands

# Check pointer status seid q evm pointer ERC1155 $CONTRACT_ADDRESS --output json # Verify transaction seid q tx $TX_HASH --output json # Check account balance seid q bank balances $ADDRESS

Best Practices

  1. Batch Operations: Use batch transfers for multiple tokens
  2. Gas Estimation: Always estimate gas for complex operations
  3. Input Validation: Validate all token IDs and amounts
  4. Error Handling: Implement comprehensive error handling
  5. Events: Emit events for cross-chain tracking
  6. Testing: Thoroughly test on testnet before mainnet deployment

Success: ERC1155 pointers provide multi-token bridging capabilities. Start with simple use cases and expand to complex token economies.

Resources

Last updated on