Skip to content

Commit

Permalink
fix: update ITS code sample token (#693)
Browse files Browse the repository at this point in the history
  • Loading branch information
Olanetsoft authored Jan 10, 2024
1 parent c9706f9 commit 93ba88b
Showing 1 changed file with 46 additions and 36 deletions.
82 changes: 46 additions & 36 deletions public/samples/interchain-token-iinterchaintoken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.8.0;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
import {ITokenManager} from "@axelar-network/interchain-token-service/contracts/interfaces/ITokenManager.sol";
import {ITokenManagerType} from "@axelar-network/interchain-token-service/contracts/interfaces/ITokenManagerType.sol";
import {IInterchainToken} from "@axelar-network/interchain-token-service/contracts/interfaces/IInterchainToken.sol";
Expand All @@ -15,45 +16,56 @@ import {AddressBytesUtils} from "@axelar-network/interchain-token-service/contra
* and security of your smart contracts before using
* in production.
*/
contract MyInterchainToken is ERC20, Ownable {
contract MyInterchainToken is ERC20, AccessControl {
using AddressBytesUtils for address;

address public creator;
bytes32 public tokenId;
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

ITokenManager public tokenManager;
IInterchainTokenService public service =
IInterchainTokenService(0xF786e21509A9D50a9aFD033B5940A2b7D872C208);

address public creator;
IInterchainTokenService(0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C);

constructor() ERC20("MyInterchainToken", "MITKN") {
// Mint 1,000 tokens to the creator
creator = msg.sender;
_mint(creator, 1000 * 10**18);
_grantRole(MINTER_ROLE, msg.sender);

// Register this token (could also be done 1-time smart contract invocation)
// Not a good practice beacuse it can't go to non-EVM chains
// Not a good practice because it can't go to non-EVM chains
deployTokenManager("");
}

function mint(address to, uint256 amount) external onlyOwner {
function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) {
_mint(to, amount);
}

function burn(address from, uint256 amount) external onlyOwner {
function burn(address from, uint256 amount) external onlyRole(MINTER_ROLE) {
_burn(from, amount);
}

function deployTokenManager(bytes32 salt) internal {
bytes memory params = service.getParamsMintBurn(
require(msg.value > 0, "Gas payment is required");

bytes memory params = tokenManager.params(
msg.sender.toBytes(),
address(this)
);
bytes32 tokenId = service.deployCustomTokenManager(

service.deployTokenManager(
salt,
"", // This field remains empty if the token manager is deployed on the local chain; however, you need to specify it when deploying on a remote chain.
ITokenManagerType.TokenManagerType.MINT_BURN,
params
params,
msg.value // gasValue
);

tokenId = service.interchainTokenId(
msg.sender,
salt
);
tokenManager = ITokenManager(service.getTokenManagerAddress(tokenId));
transferOwnership(address(tokenManager));
}

function myCustomFunction() public {
Expand All @@ -62,35 +74,32 @@ contract MyInterchainToken is ERC20, Ownable {
_mint(creator, 1000 * 10**18);
}

/*
* Deploy this token, then register it with the Interchain Token Service
* You'll be given a TokenManager which you can set here, allowing the
* local send methods to function.
*/
function setTokenManager(address _tokenManager) public onlyOwner {
tokenManager = ITokenManager(_tokenManager);
function transferMintership(address newMinter) public {
require(hasRole(MINTER_ROLE, msg.sender), "Caller is not a minter");

_revokeRole(MINTER_ROLE, msg.sender);
_grantRole(MINTER_ROLE, newMinter);
}

/**
* @notice Implementation of the interchainTransfer method
* @dev We chose to either pass `metadata` as raw data on a remote contract call, or, if no data is passed, just do a transfer.
* A different implementation could have `metadata` that tells this function which function to use or that it is used for anything else as well.
* @notice Implementation of the interchainTransfer method.
* @dev We chose to either pass `metadata` as raw data on a remote contract call, or if no data is passed, just do a transfer.
* A different implementation could use metadata to specify a function to invoke, or for other purposes as well.
* @param destinationChain The destination chain identifier.
* @param recipient The bytes representation of the address of the recipient.
* @param amount The amount of token to be transfered.
* @param metadata Either empty, to just facilitate an interchain transfer, or the data can be passed for an interchain contract call with transfer as per semantics defined by the token service.
* @param amount The amount of token to be transferred.
* @param metadata Optional metadata for the call for additional effects (such as calling a destination contract).
*/
function interchainTransfer(
string calldata destinationChain,
bytes calldata recipient,
uint256 amount,
bytes calldata metadata
) external payable {
address sender = msg.sender;

// Metadata semantics are defined by the token service and thus should be passed as-is.
tokenManager.transmitInterchainTransfer{value: msg.value}(
sender,
service.transmitInterchainTransfer{ value: msg.value }(
tokenId,
address(this),
destinationChain,
recipient,
amount,
Expand All @@ -101,12 +110,12 @@ contract MyInterchainToken is ERC20, Ownable {
/**
* @notice Implementation of the interchainTransferFrom method
* @dev We chose to either pass `metadata` as raw data on a remote contract call, or, if no data is passed, just do a transfer.
* A different implementation could have `metadata` that tells this function which function to use or that it is used for anything else as well.
* @param sender the sender of the tokens. They need to have approved `msg.sender` before this is called.
* @param destinationChain the string representation of the destination chain.
* @param recipient the bytes representation of the address of the recipient.
* @param amount the amount of token to be transfered.
* @param metadata either empty, to just facilitate a cross-chain transfer, or the data to be passed to a cross-chain contract call and transfer.
* A different implementation could use metadata to specify a function to invoke, or for other purposes as well.
* @param sender The sender of the tokens. They need to have approved `msg.sender` before this is called.
* @param destinationChain The string representation of the destination chain.
* @param recipient The bytes representation of the address of the recipient.
* @param amount The amount of token to be transferred.
* @param metadata Optional metadata for the call for additional effects (such as calling a destination contract.)
*/
function interchainTransferFrom(
address sender,
Expand All @@ -121,8 +130,9 @@ contract MyInterchainToken is ERC20, Ownable {
_approve(sender, msg.sender, _allowance - amount);
}

tokenManager.transmitInterchainTransfer{value: msg.value}(
sender,
service.transmitInterchainTransfer{ value: msg.value }(
tokenId,
address(this),
destinationChain,
recipient,
amount,
Expand Down

1 comment on commit 93ba88b

@vercel
Copy link

@vercel vercel bot commented on 93ba88b Jan 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.