Repository navigation
feat: OdraCLI upgrade and upgrade-children commands - #696
Merged
Merged
Conversation
`upgrade <Contract> --gas <amount>` upgrades a contract from the contracts file with its wasm. The arguments of the contract's `upgrade` entry point are taken from the command line like the arguments of any other entry point, and `--force-create-upgrade-group`, `--allow-key-override` and `--package-named-key` set the `UpgradeConfig`, so upgrading no longer needs a custom scenario. `Deployer::try_upgrade_with_runtime_args` upgrades with untyped arguments; `try_upgrade_with_cfg` delegates to it. The `contract` command no longer lists `upgrade` as a callable entry point. Closes #690 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`upgrade-children <Factory> --gas <amount>` upgrades all child contracts of a factory with the factory's current code, in one `batch_upgrade_child_contract` call. The upgrade arguments of a child are taken from the command line and passed to every child. The children are read from the factory's `ContractDeployed` events, listed once even though an upgrade emits the event again. `odra::consts` re-exports the names of the `odra_cfg_*` arguments the call needs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t command `upgrade-children --batch-size N` sends one `batch_upgrade_child_contract` transaction per N children. A failed transaction reports the children upgraded so far and the ones left. The `contract` command calls `new_contract` and `upgrade_child_contract` of a factory with the `odra_cfg_*` arguments its generated ref adds, which the schema does not list: the calls failed with `MissingArgument`. `batch_upgrade_child_contract`, whose arguments the schema does not describe, is no longer listed there; `upgrade-children` runs it. Both commands share the arguments in `entry_point::factory`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…upgrader `ContractUpgradeCmd::request` resolves the command line into the upgrade to run (address, upgrade args, config, gas); `exec` sends it. The tests check the request and no longer need a function-pointer mock, a thread-local call log or a temporary contracts file. `test_utils::contracts_container_with` builds a memory-backed container with one contract. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
zie1ony
approved these changes
Nov 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #690
Upgrading a contract, or all children of a factory, no longer needs a custom scenario:
Changes
upgradecommand (odra-cli/src/cmd/upgrade.rs): one subcommand per contract registered with.contract::<T>()or.named_contract::<T>(name). It upgrades the contract at the address in the contracts file withwasm/<Contract>.wasm.upgradeentry point in its schema and parsed like any other entry point's arguments. A contract without anupgradefn takes none.--gas: required.--force-create-upgrade-group: off by default.--allow-key-override [BOOL]: defaults totrue, as inUpgradeConfig::new. The flag alone also meanstrue;--allow-key-override falseturns it off.--package-named-key <NAME>: defaults to the contract name, or to thenamed_contractname.--jsonis supported, and the command works in the REPL.upgrade-childrencommand (odra-cli/src/cmd/upgrade_children.rs):upgrade-children <Factory> --gas <amount> [--<child upgrade args>]. It's listed only for registered factories, i.e. contracts withbatch_upgrade_child_contract.batch_upgrade_child_contractcall. Every child gets the same upgrade arguments, which are the arguments ofupgrade_child_contractminuscontract_name.*ContractDeployed { contract_name, contract_address }events. Each name is listed once, even though an upgrade emits the event again. The event name is matched by suffix, so children created before the factory was upgraded from another module are found too.--batch-size N: one transaction per N children, each with the--gasamount (default: all in one). If a transaction fails, the error lists the children upgraded so far and the ones left.odra_cfg_*arguments as the generated factory ref (odra_cfg_is_factory_upgrade,odra_cfg_allow_key_override,odra_cfg_create_upgrade_group).odra::constsis now re-exported for this.contractcommand on factories:new_contractandupgrade_child_contractfailed on chain withMissingArgument, because the generic call didn't send theodra_cfg_*arguments the generated factory ref adds. They're now added for factory contracts, inentry_point::factory, whichupgrade-childrenuses too.batch_upgrade_child_contractis no longer listed undercontract: its schema argument type (List<U8>) doesn't match what it actually takes, so it could never be called there.upgrade-childrencovers it.Deployer::try_upgrade_with_runtime_argsupgrades withRuntimeArgsinstead of the typedUpgradeArgs.try_upgrade_with_cfgnow delegates to it.contractcommand:upgradeis no longer listed as a callable entry point. Calling it there could not work.Testing
--gasand upgrade arguments, the config defaults and overrides, the named-contract key default, and the error for a contract missing from the contracts file. They use a mock upgrader that records its arguments.cargo test -p odra-cli, clippy, and the upgrade tests inexamplespass.upgrade-childrentests: only factories are listed, the child upgrade arguments are required andcontract_nameis rejected, children are read from events (de-duplicated, other events skipped), and the batch arguments are byte-for-byte what the generated factory ref builds.upgrade-childrenend to end on NCTL (with a temporary deploy script, not committed): deployedBetterCounterFactorywith childrenFromTen(10) andFromTwo.upgrade-children BetterCounterFactory --new_value 42upgraded both in one transaction andcontract FromTen valuereturned 42. A second run with--json --new_value 7listed each child once and the value became 7.contractcalls and batches, end to end on NCTL (temporary deploy script, not committed):contract BetterCounterFactory new_contractcreated children A, B and C.contract BetterCounterFactory upgrade_child_contract --contract_name A --new_value 5changed A from 1 to 5.upgrade-children ... --new_value 9 --batch-size 2sent 2 transactions (A, B, then C), and A then read 9.deploy, thenupgrade DogContract --gas 400000000000. The transaction executed, the package hash was unchanged, andcontract DogContract namestill worked afterwards.--jsonand--helpwere also checked.🤖 Generated with Claude Code