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

refactor(ITS): distributor -> minter #211

Merged
merged 6 commits into from
Dec 5, 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
52 changes: 22 additions & 30 deletions contracts/InterchainTokenFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -114,33 +114,33 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M

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

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

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

if (initialSupply > 0) {
bytes32 tokenId = service.interchainTokenId(TOKEN_FACTORY_DEPLOYER, salt);
Expand All @@ -150,36 +150,36 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
_setDeployerTokenBalance(tokenId, sender, initialSupply);
token.mint(address(this), initialSupply);

token.transferDistributorship(distributor);
token.transferMintership(minter);

tokenManager.removeFlowLimiter(address(this));

// If distributor == address(0), we still set it as a flow limiter for consistency with the remote token manager.
tokenManager.addFlowLimiter(distributor);
// If minter == address(0), we still set it as a flow limiter for consistency with the remote token manager.
tokenManager.addFlowLimiter(minter);

tokenManager.transferOperatorship(distributor);
tokenManager.transferOperatorship(minter);
}
}

/**
* @notice Deploys a remote interchain token on a specified destination chain.
* @param originalChainName The name of the chain where the token originally exists.
* @param salt The unique salt for deploying the token.
* @param distributor The address to distribute the token on the destination chain.
* @param minter The address to distribute the token on the destination chain.
* @param destinationChain The name of the destination chain.
* @param gasValue The amount of gas to send for the deployment.
*/
function deployRemoteInterchainToken(
string calldata originalChainName,
bytes32 salt,
address distributor,
address minter,
string memory destinationChain,
uint256 gasValue
) external payable {
string memory tokenName;
string memory tokenSymbol;
uint8 tokenDecimals;
bytes memory distributor_ = new bytes(0);
bytes memory minter_ = new bytes(0);

{
bytes32 chainNameHash_;
Expand All @@ -199,14 +199,14 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
tokenSymbol = token.symbol();
tokenDecimals = token.decimals();

if (distributor != address(0)) {
if (!token.isDistributor(distributor)) revert NotDistributor(distributor);
if (minter != address(0)) {
if (!token.isMinter(minter)) revert NotMinter(minter);

distributor_ = distributor.toBytes();
minter_ = minter.toBytes();
}
}

_deployInterchainToken(salt, destinationChain, tokenName, tokenSymbol, tokenDecimals, distributor_, gasValue);
_deployInterchainToken(salt, destinationChain, tokenName, tokenSymbol, tokenDecimals, minter_, gasValue);
}

/**
Expand All @@ -216,7 +216,7 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
* @param tokenName The name of the token.
* @param tokenSymbol The symbol of the token.
* @param tokenDecimals The number of decimals for the token.
* @param distributor The address to receive the initially minted tokens.
* @param minter The address to receive the initially minted tokens.
* @param gasValue The amount of gas to send for the transfer.
*/
function _deployInterchainToken(
Expand All @@ -225,19 +225,11 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
string memory tokenName,
string memory tokenSymbol,
uint8 tokenDecimals,
bytes memory distributor,
bytes memory minter,
uint256 gasValue
) internal {
// slither-disable-next-line arbitrary-send-eth
service.deployInterchainToken{ value: gasValue }(
salt,
destinationChain,
tokenName,
tokenSymbol,
tokenDecimals,
distributor,
gasValue
);
service.deployInterchainToken{ value: gasValue }(salt, destinationChain, tokenName, tokenSymbol, tokenDecimals, minter, gasValue);
}

/**
Expand Down
50 changes: 21 additions & 29 deletions contracts/InterchainTokenService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { IInterchainTokenExecutable } from './interfaces/IInterchainTokenExecuta
import { IInterchainTokenExpressExecutable } from './interfaces/IInterchainTokenExpressExecutable.sol';
import { ITokenManager } from './interfaces/ITokenManager.sol';

import { Operatable } from './utils/Operatable.sol';
import { Operator } from './utils/Operator.sol';

/**
* @title The Interchain Token Service
Expand All @@ -35,7 +35,7 @@ import { Operatable } from './utils/Operatable.sol';
*/
contract InterchainTokenService is
Upgradable,
Operatable,
Operator,
Pausable,
Multicall,
Create3Address,
Expand Down Expand Up @@ -298,14 +298,14 @@ contract InterchainTokenService is
/**
* @notice Used to deploy an interchain token alongside a TokenManager in another chain.
* @dev At least the `gasValue` amount of native token must be passed to the function call. `gasValue` exists because this function can be
* part of a multicall involving multiple functions that could make remote contract calls. If the `distributor` parameter is empty bytes then
* part of a multicall involving multiple functions that could make remote contract calls. If the `minter` parameter is empty bytes then
* a mint/burn TokenManager is used, otherwise a lock/unlock TokenManager is used.
* @param salt The salt to be used during deployment.
* @param destinationChain The name of the destination chain to deploy to.
* @param name The name of the token to be deployed.
* @param symbol The symbol of the token to be deployed.
* @param decimals The decimals of the token to be deployed.
* @param distributor The address that will be able to mint and burn the deployed token.
* @param minter The address that will be able to mint and burn the deployed token.
* @param gasValue The amount of native tokens to be used to pay for gas for the remote deployment.
*/
function deployInterchainToken(
Expand All @@ -314,7 +314,7 @@ contract InterchainTokenService is
string memory name,
string memory symbol,
uint8 decimals,
bytes memory distributor,
bytes memory minter,
uint256 gasValue
) external payable whenNotPaused {
address deployer = msg.sender;
Expand All @@ -324,11 +324,11 @@ contract InterchainTokenService is
bytes32 tokenId = interchainTokenId(deployer, salt);

if (bytes(destinationChain).length == 0) {
address tokenAddress = _deployInterchainToken(tokenId, distributor, name, symbol, decimals);
address tokenAddress = _deployInterchainToken(tokenId, minter, name, symbol, decimals);

_deployTokenManager(tokenId, TokenManagerType.MINT_BURN, abi.encode(distributor, tokenAddress));
_deployTokenManager(tokenId, TokenManagerType.MINT_BURN, abi.encode(minter, tokenAddress));
} else {
_deployRemoteInterchainToken(tokenId, name, symbol, decimals, distributor, destinationChain, gasValue);
_deployRemoteInterchainToken(tokenId, name, symbol, decimals, minter, destinationChain, gasValue);
}
}

Expand Down Expand Up @@ -740,15 +740,15 @@ contract InterchainTokenService is
* @param payload The encoded data payload to be processed.
*/
function _processDeployInterchainTokenPayload(bytes calldata payload) internal {
(, bytes32 tokenId, string memory name, string memory symbol, uint8 decimals, bytes memory distributorBytes) = abi.decode(
(, bytes32 tokenId, string memory name, string memory symbol, uint8 decimals, bytes memory minterBytes) = abi.decode(
payload,
(uint256, bytes32, string, string, uint8, bytes)
);
address tokenAddress;

tokenAddress = _deployInterchainToken(tokenId, distributorBytes, name, symbol, decimals);
tokenAddress = _deployInterchainToken(tokenId, minterBytes, name, symbol, decimals);

_deployTokenManager(tokenId, TokenManagerType.MINT_BURN, abi.encode(distributorBytes, tokenAddress));
_deployTokenManager(tokenId, TokenManagerType.MINT_BURN, abi.encode(minterBytes, tokenAddress));
}

/**
Expand Down Expand Up @@ -820,7 +820,7 @@ contract InterchainTokenService is
* @param name The name of the token.
* @param symbol The symbol of the token.
* @param decimals The number of decimals of the token.
* @param distributor The distributor address for the token.
* @param minter The minter address for the token.
* @param destinationChain The destination chain where the token will be deployed.
* @param gasValue The amount of gas to be paid for the transaction.
*/
Expand All @@ -829,17 +829,17 @@ contract InterchainTokenService is
string memory name,
string memory symbol,
uint8 decimals,
bytes memory distributor,
bytes memory minter,
string calldata destinationChain,
uint256 gasValue
) internal {
// slither-disable-next-line unused-return
validTokenManagerAddress(tokenId);

// slither-disable-next-line reentrancy-events
emit InterchainTokenDeploymentStarted(tokenId, name, symbol, decimals, distributor, destinationChain);
emit InterchainTokenDeploymentStarted(tokenId, name, symbol, decimals, minter, destinationChain);

bytes memory payload = abi.encode(MESSAGE_TYPE_DEPLOY_INTERCHAIN_TOKEN, tokenId, name, symbol, decimals, distributor);
bytes memory payload = abi.encode(MESSAGE_TYPE_DEPLOY_INTERCHAIN_TOKEN, tokenId, name, symbol, decimals, minter);

_callContract(destinationChain, payload, MetadataVersion.CONTRACT_CALL, gasValue);
}
Expand Down Expand Up @@ -881,33 +881,25 @@ contract InterchainTokenService is
/**
* @notice Deploys an interchain token.
* @param tokenId The ID of the token.
* @param distributorBytes The distributor address for the token.
* @param minterBytes The minter address for the token.
* @param name The name of the token.
* @param symbol The symbol of the token.
* @param decimals The number of decimals of the token.
*/
function _deployInterchainToken(
bytes32 tokenId,
bytes memory distributorBytes,
bytes memory minterBytes,
string memory name,
string memory symbol,
uint8 decimals
) internal returns (address tokenAddress) {
bytes32 salt = _getInterchainTokenSalt(tokenId);

address distributor;
if (bytes(distributorBytes).length != 0) distributor = distributorBytes.toAddress();
address minter;
if (bytes(minterBytes).length != 0) minter = minterBytes.toAddress();

(bool success, bytes memory returnData) = interchainTokenDeployer.delegatecall(
abi.encodeWithSelector(
IInterchainTokenDeployer.deployInterchainToken.selector,
salt,
tokenId,
distributor,
name,
symbol,
decimals
)
abi.encodeWithSelector(IInterchainTokenDeployer.deployInterchainToken.selector, salt, tokenId, minter, name, symbol, decimals)
);
if (!success) {
revert InterchainTokenDeploymentFailed(returnData);
Expand All @@ -918,7 +910,7 @@ contract InterchainTokenService is
}

// slither-disable-next-line reentrancy-events
emit InterchainTokenDeployed(tokenId, tokenAddress, distributor, name, symbol, decimals);
emit InterchainTokenDeployed(tokenId, tokenAddress, minter, name, symbol, decimals);
}

/**
Expand Down
34 changes: 14 additions & 20 deletions contracts/interchain-token/InterchainToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import { IInterchainToken } from '../interfaces/IInterchainToken.sol';

import { BaseInterchainToken } from './BaseInterchainToken.sol';
import { ERC20Permit } from './ERC20Permit.sol';
import { Distributable } from '../utils/Distributable.sol';
import { Minter } from '../utils/Minter.sol';

/**
* @title InterchainToken
* @notice This contract implements an interchain token which extends InterchainToken functionality.
* @dev This contract also inherits Distributable and Implementation logic.
* @dev This contract also inherits Minter and Implementation logic.
*/
contract InterchainToken is BaseInterchainToken, ERC20Permit, Distributable, IInterchainToken {
contract InterchainToken is BaseInterchainToken, ERC20Permit, Minter, IInterchainToken {
using AddressBytes for bytes;

string public name;
Expand Down Expand Up @@ -77,18 +77,12 @@ contract InterchainToken is BaseInterchainToken, ERC20Permit, Distributable, IIn
/**
* @notice Setup function to initialize contract parameters.
* @param tokenId_ The tokenId of the token.
* @param distributor The address of the token distributor.
* @param minter The address of the token minter.
* @param tokenName The name of the token.
* @param tokenSymbol The symbopl of the token.
* @param tokenDecimals The decimals of the token.
*/
function init(
bytes32 tokenId_,
address distributor,
string calldata tokenName,
string calldata tokenSymbol,
uint8 tokenDecimals
) external {
function init(bytes32 tokenId_, address minter, string calldata tokenName, string calldata tokenSymbol, uint8 tokenDecimals) external {
if (_isInitialized()) revert AlreadyInitialized();

_initialize();
Expand All @@ -102,33 +96,33 @@ contract InterchainToken is BaseInterchainToken, ERC20Permit, Distributable, IIn
tokenId = tokenId_;

/**
* @dev Set the token service as a distributor to allow it to mint and burn tokens.
* Also add the provided address as a distributor. If `address(0)` was provided,
* add it as a distributor to allow anyone to easily check that no custom distributor was set.
* @dev Set the token service as a minter to allow it to mint and burn tokens.
* Also add the provided address as a minter. If `address(0)` was provided,
* add it as a minter to allow anyone to easily check that no custom minter was set.
*/
_addDistributor(interchainTokenService_);
_addDistributor(distributor);
_addMinter(interchainTokenService_);
_addMinter(minter);

_setNameHash(tokenName);
}

/**
* @notice Function to mint new tokens.
* @dev Can only be called by the distributor address.
* @dev Can only be called by the minter address.
* @param account The address that will receive the minted tokens.
* @param amount The amount of tokens to mint.
*/
function mint(address account, uint256 amount) external onlyRole(uint8(Roles.DISTRIBUTOR)) {
function mint(address account, uint256 amount) external onlyRole(uint8(Roles.MINTER)) {
_mint(account, amount);
}

/**
* @notice Function to burn tokens.
* @dev Can only be called by the distributor address.
* @dev Can only be called by the minter address.
* @param account The address that will have its tokens burnt.
* @param amount The amount of tokens to burn.
*/
function burn(address account, uint256 amount) external onlyRole(uint8(Roles.DISTRIBUTOR)) {
function burn(address account, uint256 amount) external onlyRole(uint8(Roles.MINTER)) {
_burn(account, amount);
}
}
Loading