Skip to content

Commit

Permalink
feat: support ownership transfers in the SVM warp route tooling, fina…
Browse files Browse the repository at this point in the history
…lize Sonic deploy (hyperlane-xyz#5529)

### Description

### **Note!**
This includes
hyperlane-xyz#5575. I'd
recommend just looking at the `rust/` changes when reviewing

- Supports changing the owner and upgrade authority (assumed to be the
same address) in the SVM warp route tooling
- So when running e.g. the following, it'll also idempotently transfer
ownership / set the program upgrade authority. It defaults to the payer
as the owner.
```
cargo run -- -k ~/solana-devnet-deployer-keypair.json warp-route deploy --warp-route-name SOL-solanatestnet-sonicsvmtestnet --environment testnet4 --environments-dir ../environments --built-so-dir ../../target/deploy --token-config-file ../environments/testnet4/warp-routes/SOL-solanatestnet-sonicsvmtestnet/token-config.json  --chain-config-file ../environments/testnet4/chain-config.json --ata-payer-funding-amount 1000000
```
- I haven't gone back to update the configs for all the other deploys we
did that had manual ownership transfer. Hoping to do something like this
soon

### Drive-by changes

- none

### Related issues

- none

### Backward compatibility

- backward compatible

### Testing

- tried it out on a testnet warp deploy, worked well
  • Loading branch information
tkporter authored Feb 27, 2025
1 parent ae8f7c6 commit e8851ae
Show file tree
Hide file tree
Showing 23 changed files with 326 additions and 49 deletions.
2 changes: 1 addition & 1 deletion .registryrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
d984e8113bb795a01ffe040539a63b1227749d71
58b181ec6ce4938c15dce9aa966920ff5ef7b3b2
125 changes: 118 additions & 7 deletions rust/sealevel/client/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ use std::{

use solana_client::rpc_client::RpcClient;
use solana_program::instruction::Instruction;
use solana_sdk::{commitment_config::CommitmentConfig, pubkey::Pubkey};
use solana_sdk::{
account_utils::StateMut,
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
commitment_config::CommitmentConfig,
pubkey::Pubkey,
};

use account_utils::DiscriminatorData;
use hyperlane_sealevel_connection_client::router::RemoteRouterConfig;
Expand Down Expand Up @@ -382,12 +387,6 @@ pub(crate) fn deploy_routers<
.get(*chain_name)
.unwrap_or_else(|| panic!("Chain config not found for chain: {}", chain_name));

if let Some(configured_owner) = app_config.router_config().ownable.owner {
if configured_owner != ctx.payer_pubkey {
println!("WARNING: Ownership transfer is not yet supported in this deploy tooling, ownership is granted to the payer account");
}
}

adjust_gas_price_if_needed(chain_name.as_str(), ctx);

// Deploy - this is idempotent.
Expand Down Expand Up @@ -423,6 +422,8 @@ pub(crate) fn deploy_routers<
app_config.router_config(),
chain_config,
);

configure_upgrade_authority(ctx, &program_id, app_config.router_config(), chain_config);
}

// Now enroll all the routers.
Expand Down Expand Up @@ -540,6 +541,16 @@ fn configure_owner(
let expected_owner = Some(router_config.ownable.owner(ctx.payer_pubkey));

if actual_owner != expected_owner {
if actual_owner != Some(ctx.payer_pubkey) {
println!(
"WARNING: Ownership transfer cannot be completed for chain: {} ({}) from {:?} to {:?}, the existing owner is not the payer account",
chain_config.name,
chain_config.domain_id(),
actual_owner,
expected_owner,
);
return;
}
ctx.new_txn()
.add_with_description(
deployer.set_owner_instruction(&client, program_id, expected_owner),
Expand All @@ -552,9 +563,109 @@ fn configure_owner(
)
.with_client(&client)
.send_with_payer();

// Sanity check that it was updated!

// Sleep 5 seconds for the owner to update
std::thread::sleep(std::time::Duration::from_secs(5));

let new_owner = deployer.get_owner(&client, program_id);
assert_eq!(new_owner, expected_owner);
}
}

/// Idempotent. Attempts to set the upgrade authority to the intended owner if
/// the payer can change the upgrade authority.
fn configure_upgrade_authority(
ctx: &mut Context,
program_id: &Pubkey,
router_config: &RouterConfig,
chain_config: &ChainMetadata,
) {
let client = chain_config.client();

let actual_upgrade_authority = get_program_upgrade_authority(&client, program_id).unwrap();
let expected_upgrade_authority = Some(router_config.ownable.owner(ctx.payer_pubkey));

// And the upgrade authority is not what we expect...
if actual_upgrade_authority.is_some() && actual_upgrade_authority != expected_upgrade_authority
{
// Flag if we can't change the upgrade authority
if actual_upgrade_authority != Some(ctx.payer_pubkey) {
println!(
"WARNING: Upgrade authority transfer cannot be completed for chain: {} ({}) from {:?} to {:?}, the existing upgrade authority is not the payer account",
chain_config.name,
chain_config.domain_id(),
actual_upgrade_authority,
expected_upgrade_authority,
);
return;
}

// Then set the upgrade authority to what we expect.
ctx.new_txn()
.add_with_description(
bpf_loader_upgradeable::set_upgrade_authority(
program_id,
actual_upgrade_authority.as_ref().unwrap(),
expected_upgrade_authority.as_ref(),
),
format!(
"Setting upgrade authority for chain: {} ({}) to {:?}",
chain_config.name,
chain_config.domain_id(),
expected_upgrade_authority,
),
)
.with_client(&client)
.send_with_payer();

// Sanity check that it was updated!

// Sleep 5 seconds for the upgrade authority to update
std::thread::sleep(std::time::Duration::from_secs(5));

let new_upgrade_authority = get_program_upgrade_authority(&client, program_id).unwrap();
assert_eq!(new_upgrade_authority, expected_upgrade_authority);
}
}

fn get_program_upgrade_authority(
client: &RpcClient,
program_id: &Pubkey,
) -> Result<Option<Pubkey>, &'static str> {
let program_account = client.get_account(program_id).unwrap();
// If the program isn't upgradeable, exit
if program_account.owner != bpf_loader_upgradeable::id() {
return Err("Program is not upgradeable");
}

// The program id must actually be a program
let programdata_address = if let Ok(UpgradeableLoaderState::Program {
programdata_address,
}) = program_account.state()
{
programdata_address
} else {
return Err("Unable to deserialize program account");
};

let program_data_account = client.get_account(&programdata_address).unwrap();

// If the program data account somehow isn't deserializable, exit
let actual_upgrade_authority = if let Ok(UpgradeableLoaderState::ProgramData {
upgrade_authority_address,
slot: _,
}) = program_data_account.state()
{
upgrade_authority_address
} else {
return Err("Unable to deserialize program data account");
};

Ok(actual_upgrade_authority)
}

/// For each chain in app_configs_to_deploy, enrolls all the remote routers.
/// Idempotent.
fn enroll_all_remote_routers<
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"hyperevm": {
"hex": "0x00000000000000000000000096029bcf706fac4176492f4a05f63f7d23ce78fb",
"base58": "11111111111136DQQztgVwcA4ZYDq9QhZhnprvHp"
},
"solanamainnet": {
"hex": "0x2f7bbb8b14ccafc48c417e6ba387fa05db8df469156c7a0a923257ad994016cc",
"base58": "4CMbJtieJ7EboZZGSbXTQjW5i2sL638jFvE3dWTYG3SK"
},
"hyperevm": {
"hex": "0x00000000000000000000000096029bcf706fac4176492f4a05f63f7d23ce78fb",
"base58": "11111111111136DQQztgVwcA4ZYDq9QhZhnprvHp"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"solanamainnet": {
"type": "native",
"decimals": 9,
"interchainGasPaymaster": "AkeHBbE5JkwVppujCQQ6WuxsVsJtruBAjUo6fDCFp6fF"
"interchainGasPaymaster": "AkeHBbE5JkwVppujCQQ6WuxsVsJtruBAjUo6fDCFp6fF",
"owner": "BNGDJ1h9brgt6FFVd8No1TVAH48Fp44d7jkuydr1URwJ"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
"type": "native",
"decimals": 9,
"interchainGasPaymaster": "AkeHBbE5JkwVppujCQQ6WuxsVsJtruBAjUo6fDCFp6fF",
"interchainSecurityModule": "NtVfGz6mMXe17Jy8Mt8pvStgwFbGKHkSvxPeWn1FMNu"
"owner": "9hixEzn9pBzYG1MVWNq3jAuG7RP3vBT5ijN4UFWDVsfD"
},
"sonicsvm": {
"type": "native",
"decimals": 9,
"interchainGasPaymaster": "7VResHbw6jRVUa8qfD6e1cbzGmErcLGwgx4o7mLhZief"
"interchainGasPaymaster": "7VResHbw6jRVUa8qfD6e1cbzGmErcLGwgx4o7mLhZief",
"owner": "G8v8LHQw2pWuJiQbbPRHehsNEneMkCzRHz7vSPP2ttiZ"
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"solanamainnet": {
"hex": "0x185ca10cb892c8fbc6857a218f9071ed3d860de9cf81eaf4aac68022f34fe57b",
"base58": "2e6hyJbUpbhqbJzorDZ1m4QVTj5oPhsn2H3KBaMFVXAz"
},
"sonicsvm": {
"hex": "0x4857253b685b7aead0442c6566a83b93b28eb0125adeb490a19ef0010e8e34ad",
"base58": "5sPRiRLfmohVmtkgiGV6scrzy2C6qEZRGRUiePZf1Fs2"
},
"solanamainnet": {
"hex": "0x185ca10cb892c8fbc6857a218f9071ed3d860de9cf81eaf4aac68022f34fe57b",
"base58": "2e6hyJbUpbhqbJzorDZ1m4QVTj5oPhsn2H3KBaMFVXAz"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
"type": "collateral",
"decimals": 9,
"interchainGasPaymaster": "AkeHBbE5JkwVppujCQQ6WuxsVsJtruBAjUo6fDCFp6fF",
"interchainSecurityModule": "NtVfGz6mMXe17Jy8Mt8pvStgwFbGKHkSvxPeWn1FMNu",
"token": "SonicxvLud67EceaEzCLRnMTBqzYUUYNr93DBkBdDES"
"token": "SonicxvLud67EceaEzCLRnMTBqzYUUYNr93DBkBdDES",
"owner": "9hixEzn9pBzYG1MVWNq3jAuG7RP3vBT5ijN4UFWDVsfD"
},
"sonicsvm": {
"type": "synthetic",
"decimals": 9,
"name": "Sonic SVM",
"symbol": "SONIC",
"uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/63ae6c0a0415d480c00880e64ec8a9c3724b4e37/deployments/warp_routes/SONIC/metadata.json",
"interchainGasPaymaster": "7VResHbw6jRVUa8qfD6e1cbzGmErcLGwgx4o7mLhZief"
"interchainGasPaymaster": "7VResHbw6jRVUa8qfD6e1cbzGmErcLGwgx4o7mLhZief",
"owner": "G8v8LHQw2pWuJiQbbPRHehsNEneMkCzRHz7vSPP2ttiZ"
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"solanamainnet": {
"hex": "0x78f010d70282133383abb61fa5d2c35274fceec9485b898ddb4c6bed2eeb61d0",
"base58": "996EsR8a7MC6odE6j7sjsArmDQVqB96qWu84wHdthahm"
},
"sonicsvm": {
"hex": "0xa246507f376539e22612cb216b549c958fc9a8eaa470ef9d5320e40493adc81e",
"base58": "BvTEYSqCcfMwpAriC1vDpNhzR1JWzasRFfCPCdgsYaCd"
},
"solanamainnet": {
"hex": "0x78f010d70282133383abb61fa5d2c35274fceec9485b898ddb4c6bed2eeb61d0",
"base58": "996EsR8a7MC6odE6j7sjsArmDQVqB96qWu84wHdthahm"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
"type": "collateral",
"decimals": 6,
"interchainGasPaymaster": "AkeHBbE5JkwVppujCQQ6WuxsVsJtruBAjUo6fDCFp6fF",
"interchainSecurityModule": "NtVfGz6mMXe17Jy8Mt8pvStgwFbGKHkSvxPeWn1FMNu",
"token": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
"token": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"owner": "9hixEzn9pBzYG1MVWNq3jAuG7RP3vBT5ijN4UFWDVsfD"
},
"sonicsvm": {
"type": "synthetic",
"decimals": 6,
"name": "USD Coin",
"symbol": "USDC",
"uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/63ae6c0a0415d480c00880e64ec8a9c3724b4e37/deployments/warp_routes/USDC/metadata.json",
"interchainGasPaymaster": "7VResHbw6jRVUa8qfD6e1cbzGmErcLGwgx4o7mLhZief"
"interchainGasPaymaster": "7VResHbw6jRVUa8qfD6e1cbzGmErcLGwgx4o7mLhZief",
"owner": "G8v8LHQw2pWuJiQbbPRHehsNEneMkCzRHz7vSPP2ttiZ"
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"solanamainnet": {
"hex": "0xa844d77ea1aaa0ec8697646c2d348cc9e843e070f3bf92a3fef4ba976c56bcc5",
"base58": "CKrNt2y1e2H9728mHRVYyF2owy9eKreepRKpTMj2j8JG"
},
"sonicsvm": {
"hex": "0x988d8587170da1813da9ce24725953628f7e6fec644e1bde4874774b0f17ed30",
"base58": "BGW8geBw12Yyp4rW7Fp97a3CQRA4Czi8PdtuV2Ec3Vdy"
},
"solanamainnet": {
"hex": "0xa844d77ea1aaa0ec8697646c2d348cc9e843e070f3bf92a3fef4ba976c56bcc5",
"base58": "CKrNt2y1e2H9728mHRVYyF2owy9eKreepRKpTMj2j8JG"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
"type": "collateral",
"decimals": 6,
"interchainGasPaymaster": "AkeHBbE5JkwVppujCQQ6WuxsVsJtruBAjUo6fDCFp6fF",
"interchainSecurityModule": "NtVfGz6mMXe17Jy8Mt8pvStgwFbGKHkSvxPeWn1FMNu",
"token": "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB"
"token": "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
"owner": "9hixEzn9pBzYG1MVWNq3jAuG7RP3vBT5ijN4UFWDVsfD"
},
"sonicsvm": {
"type": "synthetic",
"decimals": 6,
"name": "Tether USD",
"symbol": "USDT",
"uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/63ae6c0a0415d480c00880e64ec8a9c3724b4e37/deployments/warp_routes/USDT/metadata.json",
"interchainGasPaymaster": "7VResHbw6jRVUa8qfD6e1cbzGmErcLGwgx4o7mLhZief"
"interchainGasPaymaster": "7VResHbw6jRVUa8qfD6e1cbzGmErcLGwgx4o7mLhZief",
"owner": "G8v8LHQw2pWuJiQbbPRHehsNEneMkCzRHz7vSPP2ttiZ"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"sonicsvm": {
"hex": "0x3cfad3af06f01be3d05923b1ad9446da5c9cb06b229b10626ae224565bccc79f",
"base58": "573J5VSCMCvUVPBBPmr13ovtEmgzU5J1kyLLJ8L3XMJ6"
},
"solanamainnet": {
"hex": "0xf341c0ab03c8e93493dc3649ec723fc23fc92d09893feeb126137a49b5923694",
"base58": "HNaDuUrtr34tXZApiAMGHG9DgAvGYsY5C6w9M2iHu59u"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"solanamainnet": {
"type": "collateral",
"decimals": 9,
"interchainGasPaymaster": "AkeHBbE5JkwVppujCQQ6WuxsVsJtruBAjUo6fDCFp6fF",
"token": "4tARAT4ssRYhrENCTxxZrmjL741eE2G23Q1zLPDW2ipf",
"owner": "9hixEzn9pBzYG1MVWNq3jAuG7RP3vBT5ijN4UFWDVsfD"
},
"sonicsvm": {
"type": "synthetic",
"decimals": 9,
"name": "adraLRT SOL (Solayer)",
"symbol": "lrtsSOL",
"uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/0342615816a74737bb5c25d7edc4cb0a691cca21/deployments/warp_routes/lrtsSOL/metadata.json",
"interchainGasPaymaster": "7VResHbw6jRVUa8qfD6e1cbzGmErcLGwgx4o7mLhZief",
"owner": "G8v8LHQw2pWuJiQbbPRHehsNEneMkCzRHz7vSPP2ttiZ"
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"solanamainnet": {
"hex": "0x7c92b922efe079f13c556b637fa1d245ebe52e5ad60d4ec3fc5d55f4ef185759",
"base58": "9PHKQFEDzedHuigSm1ZBojEX4DVF3cincGZwy3k7VHTN"
},
"sonicsvm": {
"hex": "0x07d327e3a00042d94b25cb1a910e0a34ccfb68f61dec7f0297d8a07089af2ae1",
"base58": "XYbsJQGzZgPDbt9Swd2ao54nhGSq8Wjq23MoogHvEq6"
},
"solanamainnet": {
"hex": "0x7c92b922efe079f13c556b637fa1d245ebe52e5ad60d4ec3fc5d55f4ef185759",
"base58": "9PHKQFEDzedHuigSm1ZBojEX4DVF3cincGZwy3k7VHTN"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
"type": "collateral",
"decimals": 9,
"interchainGasPaymaster": "AkeHBbE5JkwVppujCQQ6WuxsVsJtruBAjUo6fDCFp6fF",
"interchainSecurityModule": "NtVfGz6mMXe17Jy8Mt8pvStgwFbGKHkSvxPeWn1FMNu",
"token": "sSo14endRuUbvQaJS3dq36Q829a3A6BEfoeeRGJywEh"
"token": "sSo14endRuUbvQaJS3dq36Q829a3A6BEfoeeRGJywEh",
"owner": "9hixEzn9pBzYG1MVWNq3jAuG7RP3vBT5ijN4UFWDVsfD"
},
"sonicsvm": {
"type": "synthetic",
"decimals": 9,
"name": "Solayer SOL",
"symbol": "sSOL",
"uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/63ae6c0a0415d480c00880e64ec8a9c3724b4e37/deployments/warp_routes/sSOL/metadata.json",
"interchainGasPaymaster": "7VResHbw6jRVUa8qfD6e1cbzGmErcLGwgx4o7mLhZief"
"interchainGasPaymaster": "7VResHbw6jRVUa8qfD6e1cbzGmErcLGwgx4o7mLhZief",
"owner": "G8v8LHQw2pWuJiQbbPRHehsNEneMkCzRHz7vSPP2ttiZ"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"solanamainnet": {
"hex": "0xda79c46340361f23add6fad67b75babce6c62b15d39b4d80c10b9b8c71ed7515",
"base58": "Fhqa36L7sFJDiMdu54WUah9stAwRacycqHJYm3b3Geje"
},
"sonicsvm": {
"hex": "0x989f54126d7fa455b5698b6ddc9a176192a605d6858e3ed16b1829776dd5088a",
"base58": "BGmt6P5djRc3Teo3WLwXfZbEvN9pVJt7wAMgzcCc2idf"
}
}
Loading

0 comments on commit e8851ae

Please sign in to comment.