Skip to content
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

fix(Factory): tracking deployer balance #202

Merged
merged 1 commit into from
Dec 2, 2023
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
35 changes: 30 additions & 5 deletions contracts/InterchainTokenFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
bytes32 private constant CONTRACT_ID = keccak256('interchain-token-factory');
bytes32 internal constant PREFIX_CANONICAL_TOKEN_SALT = keccak256('canonical-token-salt');
bytes32 internal constant PREFIX_INTERCHAIN_TOKEN_SALT = keccak256('interchain-token-salt');
bytes32 internal constant PREFIX_DEPLOYER_BALANCE = keccak256('deployer-balance');
address private constant TOKEN_FACTORY_DEPLOYER = address(0);

/**
Expand Down Expand Up @@ -104,42 +105,50 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
tokenAddress = service.interchainTokenAddress(interchainTokenId(deployer, salt));
}

function deployerTokenBalance(bytes32 tokenId, address deployer) public view returns (uint256 deployerBalance) {
bytes32 balanceKey = keccak256(abi.encode(PREFIX_DEPLOYER_BALANCE, tokenId, deployer));
assembly {
deployerBalance := sload(balanceKey)
}
}

/**
* @notice Deploys a new interchain token with specified parameters.
* @dev Creates a new token and optionally mints an initial amount to a specified distributor.
* @param salt The unique salt for deploying the token.
* @param name The name of the token.
* @param symbol The symbol of the token.
* @param decimals The number of decimals for the token.
* @param mintAmount The amount of tokens to mint initially (can be zero).
* @param initialSupply The amount of tokens to mint initially (can be zero).
* @param distributor The address to receive the initially minted tokens.
*/
function deployInterchainToken(
bytes32 salt,
string calldata name,
string calldata symbol,
uint8 decimals,
uint256 mintAmount,
uint256 initialSupply,
address distributor
) external payable {
address sender = msg.sender;
salt = interchainTokenSalt(chainNameHash, sender, salt);
bytes memory distributorBytes = new bytes(0);

if (mintAmount > 0) {
if (initialSupply > 0) {
distributorBytes = address(this).toBytes();
} else if (distributor != address(0)) {
distributorBytes = distributor.toBytes();
}

_deployInterchainToken(salt, '', name, symbol, decimals, distributorBytes, 0);

if (mintAmount > 0) {
if (initialSupply > 0) {
bytes32 tokenId = service.interchainTokenId(TOKEN_FACTORY_DEPLOYER, salt);
IInterchainToken token = IInterchainToken(service.interchainTokenAddress(tokenId));
ITokenManager tokenManager = ITokenManager(service.tokenManagerAddress(tokenId));

token.mint(address(this), mintAmount);
_setDeployerTokenBalance(tokenId, sender, initialSupply);
token.mint(address(this), initialSupply);

token.transferDistributorship(distributor);

Expand Down Expand Up @@ -296,6 +305,13 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
uint256 amount,
uint256 gasValue
) external payable {
address sender = msg.sender;
uint256 balance = deployerTokenBalance(tokenId, sender);

if (amount > balance) revert InsufficientBalance(tokenId, sender, balance);

_setDeployerTokenBalance(tokenId, sender, balance - amount);

if (bytes(destinationChain).length == 0) {
address tokenAddress = service.interchainTokenAddress(tokenId);
IInterchainToken token = IInterchainToken(tokenAddress);
Expand All @@ -315,6 +331,8 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
address tokenAddress = service.validTokenAddress(tokenId);
IInterchainToken token = IInterchainToken(tokenAddress);

_setDeployerTokenBalance(tokenId, msg.sender, deployerTokenBalance(tokenId, msg.sender) + amount);

token.safeTransferFrom(msg.sender, address(this), amount);
}

Expand All @@ -340,4 +358,11 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
string memory symbol = IInterchainToken(token).symbol();
return token == gateway.tokenAddresses(symbol);
}

function _setDeployerTokenBalance(bytes32 tokenId, address deployer, uint256 deployerBalance) internal {
bytes32 balanceKey = keccak256(abi.encode(PREFIX_DEPLOYER_BALANCE, tokenId, deployer));
assembly {
sstore(balanceKey, deployerBalance)
}
}
}
6 changes: 3 additions & 3 deletions contracts/interfaces/IInterchainTokenFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface IInterchainTokenFactory {
error InvalidChainName();
error NotDistributor(address distributor);
error NotOperator(address operator);
error NonZeroMintAmount();
error InsufficientBalance(bytes32 tokenId, address deployer, uint256 balance);
error ApproveFailed();
error GatewayToken(address tokenAddress);

Expand Down Expand Up @@ -52,15 +52,15 @@ interface IInterchainTokenFactory {
* @param name The name of the token.
* @param symbol The symbol of the token.
* @param decimals The number of decimals for the token.
* @param mintAmount The amount of tokens to mint initially (can be zero).
* @param initialSupply The amount of tokens to mint initially (can be zero).
* @param distributor The address to receive the initially minted tokens.
*/
function deployInterchainToken(
bytes32 salt,
string calldata name,
string calldata symbol,
uint8 decimals,
uint256 mintAmount,
uint256 initialSupply,
address distributor
) external payable;

Expand Down
Loading