Skip to content

Commit

Permalink
Merge branch 'main' into feat/sui-ledger-support
Browse files Browse the repository at this point in the history
  • Loading branch information
blockchainguyy authored Dec 18, 2024
2 parents 3aa005e + 117389b commit da33885
Show file tree
Hide file tree
Showing 6 changed files with 343 additions and 5 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ Install dependencies via
- [Cosmwasm](./cosmwasm/README.md)
- [Sui](./sui/README.md)
- [Stellar](./stellar/README.md)

10 changes: 10 additions & 0 deletions sui/deploy-contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const PACKAGE_CONFIGS = {
Operators: postDeployOperators,
ITS: postDeployIts,
Squid: postDeploySquid,
Utils: postDeployUtils,
},
};

Expand Down Expand Up @@ -109,6 +110,13 @@ async function postDeployRelayerDiscovery(published, keypair, client, config, ch
};
}

async function postDeployUtils(published, keypair, client, config, chain, options) {
const [upgradeCap] = getObjectIdsByObjectTypes(published.publishTxn, [`${suiPackageAddress}::package::UpgradeCap`]);
chain.contracts.Utils.objects = {
UpgradeCap: upgradeCap,
};
}

async function postDeployGasService(published, keypair, client, config, chain, options) {
const [gasCollectorCapObjectId, gasServiceObjectId, gasServicev0ObjectId] = getObjectIdsByObjectTypes(published.publishTxn, [
`${published.packageId}::gas_service::GasCollectorCap`,
Expand Down Expand Up @@ -227,6 +235,7 @@ async function postDeployAxelarGateway(published, keypair, client, config, chain
Gateway: gateway,
UpgradeCap: upgradeCap,
Gatewayv0: gatewayv0,
OwnerCap: ownerCap,
},
domainSeparator,
operator,
Expand Down Expand Up @@ -306,6 +315,7 @@ async function deploy(keypair, client, supportedContract, config, chain, options
// Update chain configuration with deployed contract address
chain.contracts[packageName] = {
address: published.packageId,
versions: [published.packageId],
};

chain.contracts[packageName].structs = await getStructs(client, published.packageId);
Expand Down
271 changes: 268 additions & 3 deletions sui/gateway.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const { Command, Option } = require('commander');
const { Transaction } = require('@mysten/sui/transactions');
const { bcs } = require('@mysten/sui/bcs');
const { ethers } = require('hardhat');
const { bcsStructs } = require('@axelar-network/axelar-cgp-sui');
const { bcsStructs, CLOCK_PACKAGE_ID } = require('@axelar-network/axelar-cgp-sui');
const {
utils: { arrayify, keccak256, toUtf8Bytes },
constants: { HashZero },
Expand All @@ -19,8 +19,10 @@ const {
broadcast,
suiClockAddress,
saveGeneratedTx,
isAllowed,
} = require('./utils');
const secp256k1 = require('secp256k1');
const chalk = require('chalk');

const COMMAND_TYPE_APPROVE_MESSAGES = 0;
const COMMAND_TYPE_ROTATE_SIGNERS = 1;
Expand Down Expand Up @@ -185,12 +187,16 @@ async function approve(keypair, client, config, chain, contractConfig, args, opt

async function migrate(keypair, client, config, chain, contractConfig, args, options) {
const packageId = contractConfig.address;

const data = new Uint8Array(arrayify(options.migrateData || '0x'));
const tx = new Transaction();

tx.moveCall({
target: `${packageId}::gateway::migrate`,
arguments: [tx.object(contractConfig.objects.Gateway)],
arguments: [
tx.object(contractConfig.objects.Gateway),
tx.object(contractConfig.objects.OwnerCap),
tx.pure(bcs.vector(bcs.u8()).serialize(data).toBytes()),
],
});

return {
Expand Down Expand Up @@ -275,6 +281,234 @@ async function rotate(keypair, client, config, chain, contractConfig, args, opti
};
}

async function allowFunctions(keypair, client, config, chain, contractConfig, args, options) {
const packageId = contractConfig.address;

const [versionsArg, functionNamesArg] = args;

const versions = versionsArg.split(',');
const functionNames = functionNamesArg.split(',');

if (versions.length !== functionNames.length) throw new Error('Versions and Function Names must have a matching length');

const tx = new Transaction();
console.log(contractConfig.objects);

for (const i in versions) {
tx.moveCall({
target: `${packageId}::gateway::allow_function`,
arguments: [
tx.object(contractConfig.objects.Gateway),
tx.object(contractConfig.objects.OwnerCap),
tx.pure.u64(versions[i]),
tx.pure.string(functionNames[i]),
],
});
}

return {
tx,
message: 'Allow Functions',
};
}

async function disallowFunctions(keypair, client, config, chain, contractConfig, args, options) {
const packageId = contractConfig.address;

const [versionsArg, functionNamesArg] = args;

const versions = versionsArg.split(',');
const functionNames = functionNamesArg.split(',');

if (versions.length !== functionNames.length) throw new Error('Versions and Function Names must have a matching length');

const tx = new Transaction();
console.log(contractConfig.objects);

for (const i in versions) {
tx.moveCall({
target: `${packageId}::gateway::disallow_function`,
arguments: [
tx.object(contractConfig.objects.Gateway),
tx.object(contractConfig.objects.OwnerCap),
tx.pure.u64(versions[i]),
tx.pure.string(functionNames[i]),
],
});
}

return {
tx,
message: 'Disallow Functions',
};
}

async function checkVersionControl(version, options) {
const config = loadConfig(options.env);

const chain = getChainConfig(config, options.chainName);
const [keypair, client] = getWallet(chain, options);
await printWalletInfo(keypair, client, chain, options);

if (!chain.contracts?.AxelarGateway) {
throw new Error('Axelar Gateway package not found.');
}

const contractConfig = chain.contracts.AxelarGateway;
const packageId = contractConfig.versions[version];

const functions = {};
functions.approve_messages = (tx) =>
tx.moveCall({
target: `${packageId}::gateway::approve_messages`,
arguments: [tx.object(contractConfig.objects.Gateway), tx.pure.vector('u8', []), tx.pure.vector('u8', [])],
});
functions.rotate_signers = (tx) =>
tx.moveCall({
target: `${packageId}::gateway::rotate_signers`,
arguments: [
tx.object(contractConfig.objects.Gateway),
tx.object(CLOCK_PACKAGE_ID),
tx.pure.vector('u8', []),
tx.pure.vector('u8', []),
],
});
functions.is_message_approved = (tx) =>
tx.moveCall({
target: `${packageId}::gateway::is_message_approved`,
arguments: [
tx.object(contractConfig.objects.Gateway),
tx.pure.string(''),
tx.pure.string(''),
tx.pure.string(''),
tx.pure.address('0x0'),
tx.moveCall({
target: `${packageId}::bytes32::from_address`,
arguments: [tx.pure.address('0x0')],
}),
],
});
functions.is_message_executed = (tx) =>
tx.moveCall({
target: `${packageId}::gateway::is_message_executed`,
arguments: [tx.object(contractConfig.objects.Gateway), tx.pure.string(''), tx.pure.string('')],
});
functions.take_approved_message = (tx) =>
tx.moveCall({
target: `${packageId}::gateway::take_approved_message`,
arguments: [
tx.object(contractConfig.objects.Gateway),
tx.pure.string(''),
tx.pure.string(''),
tx.pure.string(''),
tx.pure.address('0x0'),
tx.pure.vector('u8', []),
],
});

functions.send_message = (tx) => {
const channel = tx.moveCall({
target: `${packageId}::channel::new`,
arguments: [],
});

const message = tx.moveCall({
target: `${packageId}::gateway::prepare_message`,
arguments: [channel, tx.pure.string(''), tx.pure.string(''), tx.pure.vector('u8', [])],
});

tx.moveCall({
target: `${packageId}::gateway::send_message`,
arguments: [tx.object(contractConfig.objects.Gateway), message],
});

tx.moveCall({
target: `${packageId}::channel::destroy`,
arguments: [channel],
});
};

functions.allow_function = (tx) =>
tx.moveCall({
target: `${packageId}::gateway::allow_function`,
arguments: [
tx.object(contractConfig.objects.Gateway),
tx.object(contractConfig.objects.OwnerCap),
tx.pure.u64(0),
tx.pure.string(''),
],
});
functions.disallow_function = (tx) =>
tx.moveCall({
target: `${packageId}::gateway::disallow_function`,
arguments: [
tx.object(contractConfig.objects.Gateway),
tx.object(contractConfig.objects.OwnerCap),
tx.pure.u64(0),
tx.pure.string(''),
],
});

if (options.allowedFunctions) {
const allowedFunctions = options.allowedFunctions === 'all' ? Object.keys(functions) : options.allowedFunctions.split(',');

for (const allowedFunction of allowedFunctions) {
const allowed = await isAllowed(client, keypair, chain, functions[allowedFunction]);
const color = allowed ? chalk.green : chalk.red;
console.log(`${allowedFunction} is ${color(allowed ? 'allowed' : 'dissalowed')}`);
}
}

if (options.disallowedFunctions) {
const disallowedFunctions = options.allowedFunctions === 'all' ? Object.keys(functions) : options.disallowedFunctions.split(',');

for (const disallowedFunction of disallowedFunctions) {
const allowed = await isAllowed(client, keypair, chain, functions[disallowedFunction]);
const color = allowed ? chalk.red : chalk.green;
console.log(`${disallowedFunction} is ${color(allowed ? 'allowed' : 'dissalowed')}`);
}
}
}

async function testNewField(value, options) {
const config = loadConfig(options.env);

const chain = getChainConfig(config, options.chainName);
const [keypair, client] = getWallet(chain, options);
await printWalletInfo(keypair, client, chain, options);

if (!chain.contracts?.AxelarGateway) {
throw new Error('Axelar Gateway package not found.');
}

const contractConfig = chain.contracts.AxelarGateway;
const packageId = contractConfig.address;

let tx = new Transaction();

tx.moveCall({
target: `${packageId}::gateway::set_new_field`,
arguments: [tx.object(contractConfig.objects.Gateway), tx.pure.u64(value)],
});

await broadcast(client, keypair, tx, 'Set new_field');
await new Promise((resolve) => setTimeout(resolve, 1000));

tx = new Transaction();

tx.moveCall({
target: `${packageId}::gateway::new_field`,
arguments: [tx.object(contractConfig.objects.Gateway)],
});

const response = await client.devInspectTransactionBlock({
transactionBlock: tx,
sender: keypair.toSuiAddress(),
});
const returnedValue = bcs.U64.parse(new Uint8Array(response.results[0].returnValues[0][0]));
console.log(`Set the value to ${value} and it was set to ${returnedValue}.`);
}

async function mainProcessor(processor, args, options) {
const config = loadConfig(options.env);

Expand Down Expand Up @@ -327,6 +561,7 @@ if (require.main === module) {
program
.command('migrate')
.description('Migrate the gateway after upgrade')
.addOption(new Option('--migrate-data <migrateData>', 'bcs encoded data to pass to the migrate function'))
.action((options) => {
mainProcessor(migrate, null, options);
});
Expand All @@ -346,6 +581,36 @@ if (require.main === module) {
mainProcessor(callContract, [destinationChain, destinationAddress, payload], options);
});

program
.command('allow-functions <versions> <functionNames>')
.description('Allow certain funcitons on the gateway')
.action((versions, functionNames, options) => {
mainProcessor(allowFunctions, [versions, functionNames], options);
});

program
.command('disallow-functions <versions> <functionNames>')
.description('Allow certain funcitons on the gateway')
.action((versions, functionNames, options) => {
mainProcessor(disallowFunctions, [versions, functionNames], options);
});

program
.command('check-version-control <version>')
.description('Check if version control works on a certain version')
.addOption(new Option('--allowed-functions <allowed-functions>', 'Functions that should be allowed on this version'))
.addOption(new Option('--disallowed-functions <disallowed-functions>', 'Functions that should be disallowed on this version'))
.action((version, options) => {
checkVersionControl(version, options);
});

program
.command('test-new-field <value>')
.description('Test the new field added for upgrade-versioned')
.action((value, options) => {
testNewField(value, options);
});

addOptionsToCommands(program, addBaseOptions, { offline: true });

program.parse();
Expand Down
1 change: 0 additions & 1 deletion sui/utils/sign-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ async function broadcast(client, keypair, tx, actionName) {
showContent: true,
},
});

printInfo(actionName || 'Tx', receipt.digest);

return receipt;
Expand Down
5 changes: 4 additions & 1 deletion sui/utils/upgrade-utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { bcs } = require('@mysten/bcs');
const { fromB64 } = require('@mysten/bcs');
const { printInfo, validateParameters } = require('../../common/utils');
const { copyMovePackage } = require('@axelar-network/axelar-cgp-sui');
const { copyMovePackage, updateMoveToml } = require('@axelar-network/axelar-cgp-sui');
const { getObjectIdsByObjectTypes, suiPackageAddress, moveDir, saveGeneratedTx } = require('./utils');
const UPGRADE_POLICIES = {
code_upgrade: 'only_additive_upgrades',
Expand Down Expand Up @@ -71,12 +71,15 @@ async function upgradePackage(client, keypair, packageToUpgrade, contractConfig,

const packageId = (result.objectChanges?.filter((a) => a.type === 'published') ?? [])[0].packageId;
contractConfig.address = packageId;
contractConfig.versions.push(packageId);
const [upgradeCap] = getObjectIdsByObjectTypes(result, [`${suiPackageAddress}::package::UpgradeCap`]);
contractConfig.objects.UpgradeCap = upgradeCap;

printInfo('Transaction Digest', JSON.stringify(result.digest, null, 2));
printInfo(`${packageName} Upgraded Address`, packageId);

updateMoveToml(packageToUpgrade.packageDir, packageId, moveDir);

return { upgraded: result, packageId };
}
}
Expand Down
Loading

0 comments on commit da33885

Please sign in to comment.