File tree Expand file tree Collapse file tree
crates/soroban-test/tests/it/integration
soroban-cli/src/commands/contract Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1+ use predicates:: prelude:: PredicateBooleanExt ;
12use soroban_cli:: {
23 commands:: {
34 contract:: { self , fetch} ,
@@ -342,6 +343,28 @@ async fn contract_data_read() {
342343 . stdout ( predicates:: str:: starts_with ( "COUNTER,2" ) ) ;
343344}
344345
346+ #[ tokio:: test]
347+ async fn extend_nonexistent_entry_errors_without_panic ( ) {
348+ // A well-formed but non-existent contract id makes the extend a no-op. The
349+ // CLI must surface a clean error rather than panic with "index out of
350+ // bounds" while inspecting the (empty) ledger entries. See issue #2599.
351+ const NONEXISTENT_ID : & str = "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSC4" ;
352+ let sandbox = & TestEnv :: new ( ) ;
353+
354+ sandbox
355+ . new_assert_cmd ( "contract" )
356+ . arg ( "extend" )
357+ . arg ( "--id" )
358+ . arg ( NONEXISTENT_ID )
359+ . arg ( "--ledgers-to-extend" )
360+ . arg ( "1" )
361+ . assert ( )
362+ . failure ( )
363+ . stderr ( predicates:: str:: contains ( "Ledger entry not found" ) )
364+ . stderr ( predicates:: str:: contains ( "index out of bounds" ) . not ( ) )
365+ . stderr ( predicates:: str:: contains ( "panicked" ) . not ( ) ) ;
366+ }
367+
345368async fn invoke_with_seed ( sandbox : & TestEnv , id : & str , seed_phrase : & str ) {
346369 invoke_with_source ( sandbox, seed_phrase, id) . await ;
347370}
Original file line number Diff line number Diff line change @@ -288,7 +288,14 @@ impl Cmd {
288288 if changes. is_empty ( ) {
289289 print. infoln ( "No changes detected, transaction was a no-op." ) ;
290290 let entry = client. get_full_ledger_entries ( & keys) . await ?;
291- let extension = entry. entries [ 0 ] . live_until_ledger_seq . unwrap_or_default ( ) ;
291+ // A no-op extend against a non-existent entry returns no entries, so
292+ // avoid indexing into an empty vec (which would panic).
293+ let extension = entry
294+ . entries
295+ . first ( )
296+ . ok_or ( Error :: LedgerEntryNotFound ) ?
297+ . live_until_ledger_seq
298+ . unwrap_or_default ( ) ;
292299
293300 return Ok ( TxnResult :: Res ( extension) ) ;
294301 }
You can’t perform that action at this time.
0 commit comments