Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
94cbe35
made deploy-token command clearer
blockchainguyy Sep 30, 2025
c99bf54
added legacy coins
blockchainguyy Sep 30, 2025
7fd0cb1
format doc
blockchainguyy Sep 30, 2025
09dc615
updated sui package
blockchainguyy Sep 30, 2025
fd314be
added documentation on ITS admin caps
blockchainguyy Sep 30, 2025
302905e
fix mint_burn mode
blockchainguyy Sep 30, 2025
134f14b
undo release changes
blockchainguyy Sep 30, 2025
b80554e
chore: revert changes
blockchainguyy Sep 30, 2025
10272bf
Merge branch 'main' into fix/sui-its-mint-burn
blockchainguyy Sep 30, 2025
f606e3a
chore: ran lint
blockchainguyy Sep 30, 2025
e3f4fc4
pay gas for both gmp calls in link coin
blockchainguyy Sep 30, 2025
86e7184
added log
blockchainguyy Oct 1, 2025
5ba2a94
Updated release doc steps
blockchainguyy Oct 1, 2025
3f7a223
fix: use gas from options
blockchainguyy Oct 1, 2025
c75cf9f
chore: update link-coin steps
blockchainguyy Oct 1, 2025
63f3d52
chore: ran lint
blockchainguyy Oct 1, 2025
a0ee1b4
Merge branch 'main' into fix/sui-its-mint-burn
drewstaylor Oct 1, 2025
79981a4
Use automatic gas estimation for its link-coin cmd
drewstaylor Oct 1, 2025
ab55d5b
Use automatic gas estimation for its link-coin cmd
drewstaylor Oct 1, 2025
f042890
Refactor register_coin_metadata and gmp call out of link_coin, into i…
drewstaylor Oct 1, 2025
2513910
npm run prettier
drewstaylor Oct 1, 2025
d66fcb1
fix gas estimation bug
drewstaylor Oct 1, 2025
282bab4
remove test data accidentally commited
drewstaylor Oct 1, 2025
2e6684f
Update docs and fix missing variable in linkCoin
drewstaylor Oct 1, 2025
572a4b0
Merge branch 'main' into fix/sui-its-mint-burn
drewstaylor Oct 1, 2025
121e3b0
fix destinationOperator param in link-coin cmd
drewstaylor Oct 1, 2025
4c93fb0
npm run prettier
drewstaylor Oct 1, 2025
b7235bb
link param is optional
drewstaylor Oct 1, 2025
706d452
link param is optional
drewstaylor Oct 1, 2025
f1d09f6
Fix: Improve coin metadata validation for new coins
cursoragent Oct 2, 2025
760d817
undo commit by cursor
blockchainguyy Oct 2, 2025
dd1ff5b
feat: update checklist
blockchainguyy Oct 2, 2025
0ef1038
fix bug in error message
drewstaylor Oct 2, 2025
f98f601
don't generate random salt, use wallet instead
drewstaylor Oct 2, 2025
3558783
clarify instruction
drewstaylor Oct 2, 2025
35f9dac
fixes asterisk prefix in destination address of link_token move call
drewstaylor Oct 2, 2025
61f3687
Add option to use a provided. Only create a salt if no salt option pr…
drewstaylor Oct 2, 2025
5909685
npm run prettier
drewstaylor Oct 2, 2025
70ab469
update salt settings for link-coin cmd in release doc
drewstaylor Oct 2, 2025
425b5e2
refactor release doc; TODO: write documentation for token linking wit…
drewstaylor Oct 2, 2025
947eee1
clarify release doc
drewstaylor Oct 2, 2025
6eaa04f
fix salt declaration for custom salt
drewstaylor Oct 2, 2025
86cab78
A note about shared salt requirements from Sui side
drewstaylor Oct 2, 2025
65932a1
clarify token manager option
drewstaylor Oct 2, 2025
289c0fe
Create case 2 tests for checklist, with Sui as destination instead of…
drewstaylor Oct 2, 2025
974ef74
update salt info in setup
drewstaylor Oct 2, 2025
7bfaad4
fix typo in var
drewstaylor Oct 2, 2025
ab1f2b3
refactor: udpated checklist
blockchainguyy Oct 3, 2025
e83725c
updated docs
blockchainguyy Oct 3, 2025
b004d0f
remove coin added to config
drewstaylor Oct 3, 2025
23a00b9
removes requirement for destination chain in cmd register-coin-metada…
drewstaylor Oct 3, 2025
0191429
update release docs after latest commit changes
drewstaylor Oct 3, 2025
54ed07e
prefer unique salt
drewstaylor Oct 3, 2025
eb1291b
Merge branch 'main' into fix/sui-its-mint-burn
drewstaylor Oct 3, 2025
0c6a7ac
adds ability to separate coin registration and link-coin using 'regis…
drewstaylor Oct 3, 2025
6a54b07
npm run prettier
drewstaylor Oct 3, 2025
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: 30 additions & 22 deletions releases/sui/2025-09-ITS-v1.2.0.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Sui ITS v1.2.0

| | **Owner** |
|----------------|----------------------------------------|
| -------------- | -------------------------------------- |
| **Created By** | @drewstaylor <[email protected]> |
| **Deployment** | @blockchainguyy <[email protected]> |

| **Network** | **Deployment Status** | **Date** |
|----------------------|-----------------------|------------|
| -------------------- | --------------------- | ---------- |
| **Devnet Amplifier** | Completed | 2025-09-18 |
| **Stagenet** | Completed | 2025-09-19 |
| **Testnet** | TBD | TBD |
Expand All @@ -19,15 +19,16 @@ Many of the deployment commands require either Owner or Operator privileges on t
Some commands require a wallet that owns the contract's admin capability (`OwnerCap`). By default, this will be the address that deployed the ITS v0 contract.

The commands requiring this capability are:
* [Upgrading the ITS move contract](#upgrading-the-its-move-contract)
* [Enabling the Upgrade](#enabling-the-upgrade)
* [Disabling the Legacy Contract](#disabling-the-legacy-contract)

- [Upgrading the ITS move contract](#upgrading-the-its-move-contract)
- [Enabling the Upgrade](#enabling-the-upgrade)
- [Disabling the Legacy Contract](#disabling-the-legacy-contract)

Migrating legacy coin metadata requires a `OperatorCap` capability. This is any address added as an operator for the affected coin. By default, the address that deployed and initialized the ITS v0 contract possesses a `OperatorCap`.

The commands requiring this capability are:
* [Migrating Legacy Tokens](#migrating-legacy-tokens)

- [Migrating Legacy Tokens](#migrating-legacy-tokens)

## Deployment

Expand All @@ -39,13 +40,20 @@ npm ci && npm run build
Create a `.env` config. Use `all` for `CHAINS` to run the cmd for every EVM chain, or set a specific chain. On `devnet-amplifier` chain name will be set to `sui-2`.

```bash
PRIVATE_KEY=<sui-deployer-key>
PRIVATE_KEY=<sui-its-admin-caps-holder>
PRIVATE_KEY_TYPE="mnemonic" # Optional
SIGNATURE_SCHEME=secp256k1
ENV=<devnet-amplifier|stagenet|testnet|mainnet>
CHAIN=sui
```

| Network | ITS Admin Caps Holder (OwnerCap, UpgradeCap, OperatorCap) |
| ---------------- | ------------------------------------------------------------------ |
| devnet-amplifier | 0x3a6ff6c3d2b12d8acd39d9bbddca1094c28081123e59ffd0dee618d36207ee88 |
| stagenet | 0x3a6ff6c3d2b12d8acd39d9bbddca1094c28081123e59ffd0dee618d36207ee88 |
| testnet | 0x3a6ff6c3d2b12d8acd39d9bbddca1094c28081123e59ffd0dee618d36207ee88 |
| mainnet | 0x980372415053fe9d09956dea38d33d295f10de3d5c5226099304fe346ce241c9 |

1. To fix the issue of some tokens not displaying correctly in wallets, we need to fetch the affected tokens. This list can be fetched before, or after the upgrade.

```bash
Expand All @@ -61,6 +69,7 @@ ts-node sui/tokens legacy-coins
```

and run

```bash
npm i
```
Expand All @@ -81,16 +90,12 @@ sui --version

4. Do the upgrade tx

- Note: use PRIVATE_KEY of `UpgradeCap` object of v0 ITS

```bash
# Upgrade InterchainTokenService v0 -> v1
ts-node sui/deploy-contract upgrade InterchainTokenService any_upgrade
```

5. Migrate version control state to enable the upgrade.

- Note: use PRIVATE_KEY of `UpgradeCap` object of v0 ITS
5. Migrate version control state to enable the upgrade.

```bash
ts-node sui/deploy-contract migrate InterchainTokenService
Expand All @@ -107,7 +112,7 @@ The following post-upgrade tasks should be performed after the rollout
- [ ] [Test ITS token deployment and transfers](#test-its-token-deployment-and-transfers)
- [ ] [Test custom token linking](#test-custom-token-linking)

### Disabling the Legacy Contract ###
### Disabling the Legacy Contract

```bash
# Disallow all functions in the legacy ITS package
Expand All @@ -132,15 +137,15 @@ ts-node sui/its check-version-control 0

1. Re-deploy the Example contract:

- Note: use PRIVATE_KEY of deployer
- Note (Optional): Preferred to use PRIVATE_KEY of deployer

```bash
ts-node sui/deploy-contract deploy Example
```

### Migrating Legacy Tokens

- Note: use PRIVATE_KEY of `UpgradeCap` object of v0 ITS
- Note: use PRIVATE_KEY of ITS Admin Caps Holder

```bash
# Migrate legacy tokens in batches of 10 coins per tx
Expand All @@ -156,38 +161,41 @@ ts-node sui/its migrate-coin-metadata-all --batch 10 --logging 10

```bash
# Register token with manager type: lock / unlock
ts-node sui/its-example deploy-token --origin LOCK "Test Token" 9
ts-node sui/its-example deploy-token [coin-symbol] "Test Token" 9 --origin

# Register token with manager type: mint / burn
ts-node sui/its-example deploy-token --tokenManagerMode "mint_burn" --mintAmount 100 --origin MINT "Test Token" 9
ts-node sui/its-example deploy-token [coin-symbol] "Test Token" 9 --tokenManagerMode "mint_burn" --mintAmount 100 --origin
```

Testing Sui <-> EVM transfers

1. Send Token Deployment to Another Chain

```bash
ts-node sui/its-example send-deployment [coin-symbol] [chain] [gas-value]
# Example:
# ts-node sui/its-example send-deployment LOCK avalanche-fuji 0.5
# ts-node sui/its-example send-deployment AYU_L avalanche 0.5
```

2. Send Tokens to an EVM Chain

```bash
ts-node sui/its-example send-token [coin-symbol] [chain] [recepient-address] [gas-value] [amount-to-send]
# Example:
# ts-node sui/its-example send-token LOCK avalanche-fuji 0xba76c6980428A0b10CFC5d8ccb61949677A61233 0.5 1000
# ts-node sui/its-example send-token AYU_L avalanche 0xba76c6980428A0b10CFC5d8ccb61949677A61233 0.5 50
```

3. Send Tokens Back to Sui, from an EVM Chain

```bash
ts-node evm/its interchain-transfer sui [token-id] [recipient] [amount-to-send] --gasValue [gas-value] -n [evm-chain]
# Example:
# ts-node evm/its interchain-transfer sui 0x334e3a13a8d0a8fc8ab5c7828fa4c664821f0a514e2ed447de9d9103352d7873 0x76f89a9b56dc580aed9f97e2b3bd03d8d24464e38522da9464c15103761c6707 25 --gasValue 5000 -n avalanche-fuji
# Example:
# ts-node evm/its interchain-transfer sui 0x334e3a13a8d0a8fc8ab5c7828fa4c664821f0a514e2ed447de9d9103352d7873 0x76f89a9b56dc580aed9f97e2b3bd03d8d24464e38522da9464c15103761c6707 5 --gasValue 5000 -n avalanche
```

### Test custom token linking

1. Deploy a custom token and link it to the token on the origin chain.
1. Deploy a custom token and link it to the token on the origin chain.

- Note: test for both lock / unlock and mint / burn tokens

Expand Down
69 changes: 64 additions & 5 deletions sui/its-example.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,69 @@ async function sendToken(keypair, client, contracts, args, options) {
arguments: [ItsToken.objects.TokenId],
});

const Coin = await txBuilder.moveCall({
target: `${SUI_PACKAGE_ID}::coin::mint`,
arguments: [ItsToken.objects.TreasuryCap, unitAmount],
typeArguments: [ItsToken.typeArgument],
});
let Coin;
const tokenManagerMode = ItsToken.tokenManagerMode || 'lock_unlock';
const isOrigin = ItsToken.objects.origin;

if (isOrigin && tokenManagerMode === 'mint_burn') {
// For origin tokens with mint_burn mode, TreasuryCap is transferred to InterchainTokenService
// Use existing coins from wallet instead of minting
const coins = await client.getCoins({
owner: walletAddress,
coinType: ItsToken.typeArgument,
});

if (!coins.data.length) {
throw new Error(
`No ${symbol} tokens found in wallet. Make sure tokens were minted during deployment or use mint-token command.`,
);
}

// Find a coin with sufficient balance or merge coins
let selectedCoin = null;
let totalBalance = 0n;

for (const coin of coins.data) {
totalBalance += BigInt(coin.balance);
if (BigInt(coin.balance) >= BigInt(unitAmount)) {
selectedCoin = coin;
break;
}
}

if (totalBalance < BigInt(unitAmount)) {
throw new Error(`Insufficient ${symbol} balance. Required: ${unitAmount}, Available: ${totalBalance}`);
}

if (selectedCoin && BigInt(selectedCoin.balance) >= BigInt(unitAmount)) {
// Use existing coin directly if it has enough balance
if (BigInt(selectedCoin.balance) > BigInt(unitAmount)) {
// Split the coin to get exact amount
const coinObject = tx.object(selectedCoin.coinObjectId);
Coin = tx.splitCoins(coinObject, [unitAmount]);
} else {
// Use the whole coin
Coin = tx.object(selectedCoin.coinObjectId);
}
} else {
// Merge multiple coins to get the required amount
const coinObjects = coins.data.map((coin) => tx.object(coin.coinObjectId));
const primaryCoin = coinObjects[0];

if (coinObjects.length > 1) {
tx.mergeCoins(primaryCoin, coinObjects.slice(1));
}

Coin = tx.splitCoins(primaryCoin, [unitAmount]);
}
} else {
// For non-origin tokens or lock_unlock mode, mint new coins using TreasuryCap
Coin = await txBuilder.moveCall({
target: `${SUI_PACKAGE_ID}::coin::mint`,
arguments: [ItsToken.objects.TreasuryCap, unitAmount],
typeArguments: [ItsToken.typeArgument],
});
}

await txBuilder.moveCall({
target: `${Example.address}::its::send_interchain_transfer_call`,
Expand Down Expand Up @@ -260,6 +318,7 @@ async function deployToken(keypair, client, contracts, args, options) {
TokenId: tokenId,
origin: options.origin,
},
tokenManagerMode: options.tokenManagerMode || 'lock_unlock', // default to lock_unlock
};
}

Expand Down