Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
94 changes: 34 additions & 60 deletions contracts/src/TokenManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ contract TokenManager is IProtocolHandler {
struct TokenInfo {
address tokenContract;
bytes32 deployTxHash;
string protocol;
string tick;
uint256 maxSupply;
uint256 mintAmount;
Expand Down Expand Up @@ -133,14 +132,41 @@ contract TokenManager is IProtocolHandler {
// Revert if token already exists
if (token.deployTxHash != bytes32(0)) revert TokenAlreadyDeployed();

_deployToken(
txHash,
tickKey,
protocolName(),
deployOp.tick,
deployOp.maxSupply,
deployOp.mintAmount
// Validate deployment parameters
if (deployOp.maxSupply == 0) revert InvalidMaxSupply();
if (deployOp.mintAmount == 0) revert InvalidMintAmount();
if (deployOp.maxSupply % deployOp.mintAmount != 0) revert MaxSupplyNotDivisibleByMintAmount();

// Deploy ERC20 clone with CREATE2 using tickKey as salt for deterministic address
address tokenAddress = erc20Template.cloneDeterministic(tickKey);

// Initialize the clone
string memory name = string.concat(protocolName(), " ", deployOp.tick);
string memory symbol = LibString.upper(deployOp.tick);

// Initialize with max supply in 18 decimals
// User maxSupply "1000000" means 1000000 * 10^18 smallest units
EthscriptionsERC20(tokenAddress).initialize(
name,
symbol,
deployOp.maxSupply * 10**18,
txHash
);

// Store token info
tokensByTick[tickKey] = TokenInfo({
tokenContract: tokenAddress,
deployTxHash: txHash,
tick: deployOp.tick,
maxSupply: deployOp.maxSupply,
mintAmount: deployOp.mintAmount,
totalMinted: 0
});

// Map deploy hash to tick key for lookups
deployToTick[txHash] = tickKey;

emit TokenDeployed(txHash, tokenAddress, deployOp.tick, deployOp.maxSupply, deployOp.mintAmount);
}

/// @notice Handle mint operation
Expand Down Expand Up @@ -302,56 +328,4 @@ contract TokenManager is IProtocolHandler {
// Use the protocol name from this handler
return keccak256(abi.encode("erc-20", tick));
}

/// @notice Deploy a new token
/// @param deployTxHash The deployment transaction hash
/// @param tickKey The tick key for storage
/// @param protocol The protocol name
/// @param tick The token tick symbol
/// @param maxSupply The maximum supply (in user units)
/// @param mintAmount The amount per mint (in user units)
function _deployToken(
bytes32 deployTxHash,
bytes32 tickKey,
string memory protocol,
string memory tick,
uint256 maxSupply,
uint256 mintAmount
) private {
if (maxSupply == 0) revert InvalidMaxSupply();
if (mintAmount == 0) revert InvalidMintAmount();
if (maxSupply % mintAmount != 0) revert MaxSupplyNotDivisibleByMintAmount();

// Deploy ERC20 clone with CREATE2 using tickKey as salt for deterministic address
address tokenAddress = erc20Template.cloneDeterministic(tickKey);

// Initialize the clone
string memory name = string.concat(protocol, " ", tick);
string memory symbol = LibString.upper(tick);

// Initialize with max supply in 18 decimals
// User maxSupply "1000000" means 1000000 * 10^18 smallest units
EthscriptionsERC20(tokenAddress).initialize(
name,
symbol,
maxSupply * 10**18,
deployTxHash
);

// Store token info
tokensByTick[tickKey] = TokenInfo({
tokenContract: tokenAddress,
deployTxHash: deployTxHash,
protocol: protocol,
tick: tick,
maxSupply: maxSupply,
mintAmount: mintAmount,
totalMinted: 0
});

// Map deploy hash to tick key for lookups
deployToTick[deployTxHash] = tickKey;

emit TokenDeployed(deployTxHash, tokenAddress, tick, maxSupply, mintAmount);
}
}
1 change: 0 additions & 1 deletion contracts/test/EthscriptionsToken.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ contract EthscriptionsTokenTest is TestSetup {
// Verify token was deployed
TokenManager.TokenInfo memory tokenInfo = tokenManager.getTokenInfo(DEPLOY_TX_HASH);

assertEq(tokenInfo.protocol, "erc-20");
assertEq(tokenInfo.tick, "TEST");
assertEq(tokenInfo.maxSupply, 1000000);
assertEq(tokenInfo.mintAmount, 1000);
Expand Down
13 changes: 6 additions & 7 deletions lib/token_reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,24 +47,23 @@ def self.get_token(tick, block_tag: 'latest')
# struct TokenInfo {
# address tokenContract;
# bytes32 deployTxHash;
# string protocol;
# string tick;
# uint256 maxSupply;
# uint256 mintAmount;
# uint256 totalMinted;
# }
output_types = ['(address,bytes32,string,string,uint256,uint256,uint256)']
output_types = ['(address,bytes32,string,uint256,uint256,uint256)']
decoded = Eth::Abi.decode(output_types, [result.delete_prefix('0x')].pack('H*'))
token_tuple = decoded[0]

{
tokenContract: token_tuple[0],
deployTxHash: '0x' + token_tuple[1].unpack1('H*'),
protocol: token_tuple[2],
tick: token_tuple[3],
maxSupply: token_tuple[4],
mintLimit: token_tuple[5], # mintAmount field is used as mintLimit
totalMinted: token_tuple[6],
protocol: 'erc-20', # Always erc-20 for TokenManager
tick: token_tuple[2],
maxSupply: token_tuple[3],
mintLimit: token_tuple[4], # mintAmount field is used as mintLimit
totalMinted: token_tuple[5],
# For backwards compatibility, add deployer field (not available in TokenInfo)
deployer: nil,
ethscriptionId: '0x' + token_tuple[1].unpack1('H*') # deployTxHash is the ethscriptionId
Expand Down
Loading