Skip to content
Draft
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
49 changes: 49 additions & 0 deletions .github/workflows/sui.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Sui CI

on:
push:
branches: [ main ]
paths:
- 'sui/**'
- '.github/workflows/sui.yaml'
pull_request:
paths:
- 'sui/**'
- '.github/workflows/sui.yaml'

env:
SUI_VERSION: "1.74.1"

jobs:
test:
name: Build and Test
runs-on: ubuntu-latest

defaults:
run:
working-directory: sui

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install Sui CLI
run: |
ASSET="sui-mainnet-v${SUI_VERSION}-ubuntu-x86_64.tgz"
URL="https://github.com/MystenLabs/sui/releases/download/mainnet-v${SUI_VERSION}/${ASSET}"
curl -fsSL "$URL" -o sui.tgz
mkdir -p sui-bin
tar -xzf sui.tgz -C sui-bin
sudo mv sui-bin/sui /usr/local/bin/
rm -rf sui.tgz sui-bin
sui --version

- name: Build
run: sui move build

- name: Run tests
run: sui move test

- name: Build token template
working-directory: sui/token_template
run: sui move build
53 changes: 53 additions & 0 deletions .github/workflows/update-contracts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ on:
workflow_dispatch:

name: Update Contracts

env:
APTOS_CLI_VERSION: "9.2.0"
SUI_VERSION: "1.74.1"

jobs:
update-contracts:
runs-on: warp-ubuntu-2404-x64-16x
Expand Down Expand Up @@ -67,6 +72,48 @@ jobs:
path: solana/target/idl/bridge_token_factory.json
if-no-files-found: error

- name: Install Aptos CLI
run: |
ASSET="aptos-cli-${APTOS_CLI_VERSION}-Linux-x86_64.zip"
URL="https://github.com/aptos-labs/aptos-core/releases/download/aptos-cli-v${APTOS_CLI_VERSION}/${ASSET}"
curl -fsSL "$URL" -o aptos-cli.zip
unzip -q aptos-cli.zip
sudo mv aptos /usr/local/bin/
rm aptos-cli.zip
aptos --version

# Reference bytecode compiled with the test/CI placeholder address
# (Aptos bytecode embeds the named address; deployments recompile
# with the deployer's address).
- name: Build Aptos contract
working-directory: aptos
run: aptos move compile --save-metadata --named-addresses omni_bridge=0xCAFE
timeout-minutes: 30

- name: Install Sui CLI
run: |
ASSET="sui-mainnet-v${SUI_VERSION}-ubuntu-x86_64.tgz"
URL="https://github.com/MystenLabs/sui/releases/download/mainnet-v${SUI_VERSION}/${ASSET}"
curl -fsSL "$URL" -o sui.tgz
mkdir -p sui-bin
tar -xzf sui.tgz -C sui-bin
sudo mv sui-bin/sui /usr/local/bin/
rm -rf sui.tgz sui-bin
sui --version
# Create a client config now, on a step whose stdout is discarded.
# Otherwise the first `sui` invocation that needs one (the build
# step below) prints the interactive config-creation prose — and a
# generated key's recovery phrase — to stdout, corrupting the
# captured base64 JSON artifact. `sui client` is offline here.
sui client --yes envs >/dev/null 2>&1

# Sui packages publish from the 0x0 placeholder, so both the bytecode
# modules and the base64 publish payload are directly usable.
- name: Build Sui contract
working-directory: sui
run: sui move build --dump-bytecode-as-base64 > sui_omni_bridge.json
timeout-minutes: 30

- name: Archive built WASM files
env:
RAW_TAG: ${{ github.ref_name }}
Expand All @@ -77,6 +124,12 @@ jobs:
find ./near/target/near -name "*.wasm" -exec cp {} artifacts/ \;
cp ./solana/target/verifiable/bridge_token_factory.so artifacts
cp ./solana/target/verifiable/bridge_token_factory_fogo.so artifacts
zip -j artifacts/aptos_omni_bridge.zip \
aptos/build/OmniBridge/bytecode_modules/*.mv \
aptos/build/OmniBridge/package-metadata.bcs
zip -j artifacts/sui_omni_bridge.zip \
sui/build/OmniBridge/bytecode_modules/*.mv
cp sui/sui_omni_bridge.json artifacts/
zip -j "$ZIP_NAME" artifacts/*
shell: bash

Expand Down
1 change: 1 addition & 0 deletions near/omni-bridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,7 @@ impl Contract {
s if s.starts_with("fogo") => ChainKind::Fogo,
s if s.starts_with("strk") || s.starts_with("starknet") => ChainKind::Strk,
s if s.starts_with("aptos") => ChainKind::Aptos,
s if s.starts_with("sui") => ChainKind::Sui,
_ => env::panic_str(&BridgeError::CannotDetermineOriginChain.as_ref()),
};

Expand Down
6 changes: 6 additions & 0 deletions near/omni-tests/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,12 @@ pub mod tests {
.unwrap()
}

pub fn sui_factory_address() -> OmniAddress {
"sui:0x05558831a603eca8cd69a42d4251f08de3573039b69f23972265cac76639f1cf"
.parse()
.unwrap()
}

pub fn sol_factory_address() -> OmniAddress {
"sol:11111111111111111111111111111111".parse().unwrap()
}
Expand Down
6 changes: 4 additions & 2 deletions near/omni-tests/src/omni_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ mod tests {
bnb_token_address, eth_eoa_address, eth_factory_address, eth_token_address,
fogo_factory_address, get_test_deploy_token_args, hyperevm_factory_address, locker_wasm,
mock_global_contract_deployer_wasm, mock_prover_wasm, omni_token_wasm, pol_factory_address,
sol_factory_address, sol_token_address, strk_factory_address, token_deployer_wasm,
wasm_code_hash, GLOBAL_STORAGE_COST_PER_BYTE, NEP141_DEPOSIT, STORAGE_DEPOSIT_PER_BYTE,
sol_factory_address, sol_token_address, strk_factory_address, sui_factory_address,
token_deployer_wasm, wasm_code_hash, GLOBAL_STORAGE_COST_PER_BYTE, NEP141_DEPOSIT,
STORAGE_DEPOSIT_PER_BYTE,
};

const PREV_TOKEN_DEPLOYER_WASM_FILEPATH: &str = "src/data/legacy_token_deployer-0.2.4.wasm";
Expand Down Expand Up @@ -144,6 +145,7 @@ mod tests {
ChainKind::HyperEvm => hyperevm_factory_address(),
ChainKind::Strk => strk_factory_address(),
ChainKind::Aptos => aptos_factory_address(),
ChainKind::Sui => sui_factory_address(),
ChainKind::Near | ChainKind::Btc | ChainKind::Zcash => panic!("Unsupported chain"),
};

Expand Down
31 changes: 27 additions & 4 deletions near/omni-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ pub enum ChainKind {
Fogo,
#[serde(alias = "aptos")]
Aptos,
#[serde(alias = "sui")]
Sui,
}

impl ChainKind {
Expand All @@ -101,7 +103,8 @@ impl ChainKind {
| Self::Sol
| Self::Strk
| Self::Fogo
| Self::Aptos => false,
| Self::Aptos
| Self::Sui => false,
}
}

Expand All @@ -119,7 +122,8 @@ impl ChainKind {
| Self::Strk
| Self::Abs
| Self::Fogo
| Self::Aptos => false,
| Self::Aptos
| Self::Sui => false,
}
}

Expand All @@ -137,7 +141,8 @@ impl ChainKind {
| Self::Abs
| Self::Btc
| Self::Zcash
| Self::Aptos => false,
| Self::Aptos
| Self::Sui => false,
}
}
}
Expand Down Expand Up @@ -174,6 +179,7 @@ impl TryFrom<u8> for ChainKind {
11 => Ok(Self::Abs),
12 => Ok(Self::Fogo),
13 => Ok(Self::Aptos),
14 => Ok(Self::Sui),
_ => Err(format!("{input:?} invalid chain kind")),
}
}
Expand All @@ -183,6 +189,10 @@ pub type EvmAddress = H160;
pub type UTXOChainAddress = String;
pub type StarknetAddress = H256;
pub type AptosAddress = H256;
/// Sui coins are types, not addresses: for tokens this carries
/// `keccak256(canonical coin type string)`; for accounts, the native
/// 32-byte Sui address.
pub type SuiAddress = H256;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sui treats coins differently as in Aptos, I decided to keep H256 for more similarity between move-related chains and store hash as an address, but maybe it's more transparent to use bounded string here


pub const ZERO_ACCOUNT_ID: &str =
"0000000000000000000000000000000000000000000000000000000000000000";
Expand All @@ -204,6 +214,7 @@ pub enum OmniAddress {
Abs(EvmAddress),
Fogo(SolAddress),
Aptos(AptosAddress),
Sui(SuiAddress),
}

impl OmniAddress {
Expand All @@ -224,6 +235,7 @@ impl OmniAddress {
ChainKind::Abs => Ok(Self::Abs(H160::ZERO)),
ChainKind::Fogo => Ok(Self::Fogo(SolAddress::ZERO)),
ChainKind::Aptos => Ok(Self::Aptos(H256::ZERO)),
ChainKind::Sui => Ok(Self::Sui(H256::ZERO)),
}
}

Expand Down Expand Up @@ -267,6 +279,7 @@ impl OmniAddress {
)),
ChainKind::Strk => Ok(Self::Strk(H256(address.try_into().map_err(stringify)?))),
ChainKind::Aptos => Ok(Self::Aptos(H256(address.try_into().map_err(stringify)?))),
ChainKind::Sui => Ok(Self::Sui(H256(address.try_into().map_err(stringify)?))),
}
}

Expand All @@ -286,6 +299,7 @@ impl OmniAddress {
Self::Abs(_) => ChainKind::Abs,
Self::Fogo(_) => ChainKind::Fogo,
Self::Aptos(_) => ChainKind::Aptos,
Self::Sui(_) => ChainKind::Sui,
}
}

Expand All @@ -305,6 +319,7 @@ impl OmniAddress {
Self::Abs(address) => ("abs", address.to_string()),
Self::Fogo(address) => ("fogo", address.to_string()),
Self::Aptos(address) => ("aptos", address.to_string()),
Self::Sui(address) => ("sui", address.to_string()),
};

if skip_zero_address && self.is_zero() {
Expand All @@ -326,7 +341,7 @@ impl OmniAddress {
Self::Near(address) => *address == ZERO_ACCOUNT_ID,
Self::Sol(address) | Self::Fogo(address) => address.is_zero(),
Self::Btc(address) | Self::Zcash(address) => address.is_empty(),
Self::Strk(address) | Self::Aptos(address) => address.is_zero(),
Self::Strk(address) | Self::Aptos(address) | Self::Sui(address) => address.is_zero(),
}
}

Expand All @@ -336,6 +351,7 @@ impl OmniAddress {
Self::Fogo(address) => Self::hashed_token_prefix("fogo", &H256(address.0)),
Self::Strk(address) => Self::hashed_token_prefix("strk", address),
Self::Aptos(address) => Self::hashed_token_prefix("aptos", address),
Self::Sui(address) => Self::hashed_token_prefix("sui", address),
Self::Eth(address) => {
if self.is_zero() {
"eth".to_string()
Expand Down Expand Up @@ -426,6 +442,7 @@ impl FromStr for OmniAddress {
"strk" => Ok(Self::Strk(recipient.parse().map_err(stringify)?)),
"fogo" => Ok(Self::Fogo(recipient.parse().map_err(stringify)?)),
"aptos" => Ok(Self::Aptos(recipient.parse().map_err(stringify)?)),
"sui" => Ok(Self::Sui(recipient.parse().map_err(stringify)?)),
_ => Err(format!("Chain {chain} is not supported")),
}
}
Expand Down Expand Up @@ -971,6 +988,12 @@ pub fn get_native_token_address(chain_kind: ChainKind) -> Result<OmniAddress, St
ChainKind::Aptos => OmniAddress::from_str(
"aptos:0x000000000000000000000000000000000000000000000000000000000000000a",
),
// Sui coins are identified by keccak256 of the canonical coin type
// string; this is keccak256(b"0000...0002::sui::SUI") — identical
// on mainnet/testnet/devnet since 0x2::sui::SUI is a framework type.
ChainKind::Sui => OmniAddress::from_str(
"sui:0x6696387aecbb705205026783042f803871c190570dd0a57882d9d35ee0df700c",
),
ChainKind::Eth
| ChainKind::Near
| ChainKind::Sol
Expand Down
Loading
Loading