Skip to content

Commit

Permalink
feat: add stellar upgrader contract to the deploy-contract.js script
Browse files Browse the repository at this point in the history
  • Loading branch information
cgorenflo committed Dec 24, 2024
1 parent 117389b commit e2b3466
Showing 1 changed file with 53 additions and 6 deletions.
59 changes: 53 additions & 6 deletions stellar/deploy-contract.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
'use strict';

const { Address, nativeToScVal, scValToNative, Operation, StrKey } = require('@stellar/stellar-sdk');
const { Address, nativeToScVal, scValToNative, Operation, StrKey, xdr, authorizeInvocation, rpc } = require('@stellar/stellar-sdk');
const { Command, Option } = require('commander');
const { loadConfig, printInfo, saveConfig } = require('../evm/utils');
const { getWallet, broadcast, serializeValue, addBaseOptions } = require('./utils');
const { getWallet, broadcast, serializeValue, addBaseOptions, getNetworkPassphrase } = require('./utils');
const { getDomainSeparator, getChainConfig } = require('../common');
const { prompt, validateParameters } = require('../common/utils');
const { weightedSignersToScVal } = require('./type-utils');
Expand Down Expand Up @@ -74,6 +74,10 @@ async function getInitializeArgs(config, chain, contractName, wallet, options) {
return { owner, gasCollector };
}

case 'upgrader': {
return {};
}

case 'example': {
const gatewayAddress = nativeToScVal(Address.fromString(chain?.contracts?.axelar_gateway?.address), { type: 'address' });
const gasServiceAddress = nativeToScVal(Address.fromString(chain?.contracts?.axelar_gas_service?.address), { type: 'address' });
Expand Down Expand Up @@ -139,30 +143,71 @@ async function uploadWasm(filePath, wallet, chain) {

async function upgrade(options, _, chain, contractName) {
const { wasmPath, yes } = options;
const contractAddress = chain.contracts[contractName].address;
const uncheckedContractAddress = chain.contracts[contractName].address;
const wallet = await getWallet(chain, options);

if (prompt(`Proceed with upgrade on ${chain.name}?`, yes)) {
return;
}

validateParameters({
isNonEmptyString: { contractAddress },
isNonEmptyString: { uncheckedContractAddress },
});

const contractAddress = Address.fromString(uncheckedContractAddress);

const newWasmHash = await uploadWasm(wasmPath, wallet, chain);
printInfo('New Wasm hash', serializeValue(newWasmHash));

const operation = Operation.invokeContractFunction({
contract: contractAddress,
contract: chain.contracts.upgrader.address,
function: 'upgrade',
args: [nativeToScVal(newWasmHash)],
args: [
nativeToScVal(contractAddress),
nativeToScVal(options.newVersion),
nativeToScVal(newWasmHash),
nativeToScVal([options.migrationData]),
],
auth: await createUpgradeAuths(contractAddress, newWasmHash, options.migrationData, chain, wallet),
});

await broadcast(operation, wallet, chain, 'Upgraded contract', options);
chain.contracts[contractName].wasmHash = serializeValue(newWasmHash);
printInfo('Contract upgraded successfully!', contractAddress);
}

async function createUpgradeAuths(contractAddress, newWasmHash, migrationData, chain, wallet) {
// 20 seems a reasonable number of ledgers to allow for the upgrade to take effect
const validUntil = await new rpc.Server(chain.rpc).getLatestLedger().then((info) => info.sequence + 20);

return Promise.all(
[
createAuthorizedFunc(contractAddress, 'upgrade', [nativeToScVal(newWasmHash)]),
createAuthorizedFunc(contractAddress, 'migrate', [nativeToScVal(migrationData)]),
].map((auth) =>
authorizeInvocation(
wallet,
validUntil,
new xdr.SorobanAuthorizedInvocation({
function: auth,
subInvocations: [],
}),
wallet.publicKey(),
getNetworkPassphrase(chain.networkType),
),
),
);
}

const createAuthorizedFunc = (contractAddress, functionName, args) =>
xdr.SorobanAuthorizedFunction.sorobanAuthorizedFunctionTypeContractFn(
new xdr.InvokeContractArgs({
contractAddress: contractAddress.toScAddress(),
functionName,
args,
}),
);

async function mainProcessor(options, processor, contractName) {
const config = loadConfig(options.env);
const chain = getChainConfig(config, options.chainName);
Expand Down Expand Up @@ -200,6 +245,8 @@ function main() {
.description('Upgrade a Stellar contract')
.argument('<contract-name>', 'contract name to deploy')
.addOption(new Option('--wasm-path <wasmPath>', 'path to the WASM file'))
.addOption(new Option('--new-version <newVersion>', 'new version of the contract'))
.addOption(new Option('--migration-data <migrationData>', 'migration data'))
.action((contractName, options) => {
mainProcessor(options, upgrade, contractName);
});
Expand Down

0 comments on commit e2b3466

Please sign in to comment.