-
Notifications
You must be signed in to change notification settings - Fork 25
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
[TASK] Design a cross-chain asset registry for evm restaked assets #814
Comments
Cross chain asset restakingChallenge : How to mint/represent foreign chain restaked tokens on tangle Synthetic Asset = foreign restaked token 1. Using Asset Precompile to Mint Synthetic AssetsFor every restaked token, a contract factory will exist on tangle evm, the tangle evm contract will first check if an asset exists to represent the “foreign asset”, if it does then use that, else call the assets precompile to create an asset. In both cases, the next step is to call the assets precompile and then mint the synthetic assets. Example of token factory : // SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// Interface for the Assets Precompile
interface IAssetsPrecompile {
function exists(address foreignAsset) external view returns (bool);
function createAsset(address foreignAsset, string memory name, string memory symbol, uint8 decimals) external returns (address);
function mint(address asset, address to, uint256 amount) external;
}
contract TokenFactory {
address public assetsPrecompile; // Address of the Assets Precompile contract
// Mapping to store foreign asset -> synthetic asset
mapping(address => address) public foreignToSynthetic;
// Event logs
event AssetCreated(address indexed foreignAsset, address indexed syntheticAsset);
event SyntheticMinted(address indexed syntheticAsset, address indexed to, uint256 amount);
// Constructor to initialize the assets precompile address
constructor(address _assetsPrecompile) {
assetsPrecompile = _assetsPrecompile;
}
/**
* @dev Checks if a synthetic asset exists for the given foreign asset.
* If not, it creates one using the assets precompile.
* Then mints synthetic tokens for the specified recipient.
*
* @param foreignAsset Address of the foreign asset.
* @param to Address to mint the synthetic tokens to.
* @param amount Amount of synthetic tokens to mint.
*/
function handleRestake(address foreignAsset, address to, uint256 amount) external {
address syntheticAsset = foreignToSynthetic[foreignAsset];
// Check if the synthetic asset already exists
if (syntheticAsset == address(0)) {
// Call the assets precompile to check if the asset exists
bool exists = IAssetsPrecompile(assetsPrecompile).exists(foreignAsset);
if (!exists) {
// If the asset does not exist, create a new synthetic asset
string memory name = string(abi.encodePacked("Synthetic ", toString(foreignAsset)));
string memory symbol = string(abi.encodePacked("s", shortAddress(foreignAsset)));
uint8 decimals = 18; // Default decimals, can be adjusted
syntheticAsset = IAssetsPrecompile(assetsPrecompile).createAsset(foreignAsset, name, symbol, decimals);
foreignToSynthetic[foreignAsset] = syntheticAsset;
emit AssetCreated(foreignAsset, syntheticAsset);
}
}
// Mint the synthetic tokens
IAssetsPrecompile(assetsPrecompile).mint(syntheticAsset, to, amount);
emit SyntheticMinted(syntheticAsset, to, amount);
}
} Advantages:Efficiency: Simpler to manage, all “tokens” are assets, so no need to add special logic for handling deposit to restake pallet. (asset-id already exists) Disadvantages:Dependence on Native Features: Tightly coupled with the underlying blockchain architecture. 2. Using token factory contract to mint synthetic asset on evm (not using assets pallet)In this approach, a custom Token Factory Contract is deployed to manage the creation and minting of synthetic assets directly on the EVM chain without relying on the native Assets Pallet. // Minimal ERC-20 Interface
interface IERC20 {
function mint(address to, uint256 amount) external;
function burn(address from, uint256 amount) external;
}
// Token Factory Contract
contract TokenFactory {
// Mapping of foreign asset to synthetic token contract
mapping(address => address) public foreignToSynthetic;
// Events
event SyntheticCreated(address indexed foreignAsset, address indexed syntheticToken);
event SyntheticMinted(address indexed syntheticToken, address indexed to, uint256 amount);
event SyntheticBurned(address indexed syntheticToken, address indexed from, uint256 amount);
/**
* @dev Creates a synthetic token for the given foreign asset if it doesn't already exist.
* @param foreignAsset The address of the foreign asset.
* @param name The name of the synthetic token.
* @param symbol The symbol of the synthetic token.
*/
function createSynthetic(address foreignAsset, string memory name, string memory symbol) external {
require(foreignToSynthetic[foreignAsset] == address(0), "Synthetic token already exists");
// Deploy a new synthetic token (ERC-20) contract
SyntheticToken syntheticToken = new SyntheticToken(name, symbol);
// Map the foreign asset to the synthetic token
foreignToSynthetic[foreignAsset] = address(syntheticToken);
emit SyntheticCreated(foreignAsset, address(syntheticToken));
}
/**
* @dev Mints synthetic tokens for a user.
* @param foreignAsset The address of the foreign asset.
* @param to The address to receive the synthetic tokens.
* @param amount The amount of synthetic tokens to mint.
*/
function mintSynthetic(address foreignAsset, address to, uint256 amount) external {
address syntheticToken = foreignToSynthetic[foreignAsset];
require(syntheticToken != address(0), "Synthetic token does not exist");
// Mint synthetic tokens
IERC20(syntheticToken).mint(to, amount);
emit SyntheticMinted(syntheticToken, to, amount);
}
/**
* @dev Burns synthetic tokens from a user.
* @param foreignAsset The address of the foreign asset.
* @param from The address holding the synthetic tokens.
* @param amount The amount of synthetic tokens to burn.
*/
function burnSynthetic(address foreignAsset, address from, uint256 amount) external {
address syntheticToken = foreignToSynthetic[foreignAsset];
require(syntheticToken != address(0), "Synthetic token does not exist");
// Burn synthetic tokens
IERC20(syntheticToken).burn(from, amount);
emit SyntheticBurned(syntheticToken, from, amount);
}
} Advantages:Efficiency: Easier to manage/modify since it only uses solidity features Disadvantages:Need to figure out a way to generate an asset-id for all assets 3. Not minting synthetic token but simply maintain a recordNot recommended since we need the pallet to handle records in multiple ways, also slashing become difficult |
Open questions:
|
My PR in tangle-network/tnt-core#18 already does proposal #2. I don't use a factory pattern/design but it checks whether the asset exists for metadata it relates to (what bridge sent the message, what asset is it) and then creates a new ERC20. This ERC20 will eventually be stored and custodied by the For now it's not implemented ofc how that actually will generate asset IDs for the assets it holds. |
I also like proposal 2 because 1 does not solve the problem of dealing with bridged ERC20s anyway! Or ERC20s that users created on Tangle, i.e. LRTs that may interact with the system in novel way. Unless you envision adapting proposal 1 to support any future ERC20 on Tangle EVM through some precompile function for allocating an ID. |
The goal is to design and implement a crosschain asset-registration logic so that we can restake from other evm chains (and message is then passed to tangle).
The text was updated successfully, but these errors were encountered: