diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/src/lib.rs b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/src/lib.rs index 1f1964505..7dc1e7087 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/src/lib.rs +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/src/lib.rs @@ -1,6 +1,6 @@ #![no_std] use soroban_sdk::{ - contract, contractimpl, log, symbol_short, vec, Address, Env, String, Symbol, Vec, + contract, contractimpl, log, symbol_short, vec, Address, BytesN, Env, String, Symbol, Vec, }; const COUNTER: Symbol = symbol_short!("COUNTER"); @@ -46,6 +46,10 @@ impl Contract { env.prng().u64_in_range(low..=high) } + pub fn upgrade_contract(env: Env, hash: BytesN<32>) { + env.deployer().update_current_contract_wasm(hash); + } + #[allow(unused_variables)] pub fn multi_word_cmd(env: Env, contract_owner: String) {} /// Logs a string with `hello ` in front. diff --git a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go index df21d6b65..3256e38e6 100644 --- a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go +++ b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go @@ -232,9 +232,9 @@ func TestSimulateTransactionSucceeds(t *testing.T) { }, }, }, - Instructions: 5733936, + Instructions: 6070660, ReadBytes: 48, - WriteBytes: 6576, + WriteBytes: 7060, }, RefundableFee: 20056, } @@ -1015,3 +1015,118 @@ func TestSimulateInvokePrng_u64_in_range(t *testing.T) { require.LessOrEqual(t, uint64(*obtainedResult.U64), uint64(high)) require.GreaterOrEqual(t, uint64(*obtainedResult.U64), uint64(low)) } + +func TestSimulateSystemEvent(t *testing.T) { + test := NewTest(t) + + ch := jhttp.NewChannel(test.sorobanRPCURL(), nil) + client := jrpc2.NewClient(ch, nil) + + sourceAccount := keypair.Root(StandaloneNetworkPassphrase) + address := sourceAccount.Address() + account := txnbuild.NewSimpleAccount(address, 0) + + helloWorldContract := getHelloWorldContract(t) + + params := preflightTransactionParams(t, client, txnbuild.TransactionParams{ + SourceAccount: &account, + IncrementSequenceNum: true, + Operations: []txnbuild.Operation{ + createInstallContractCodeOperation(account.AccountID, helloWorldContract), + }, + BaseFee: txnbuild.MinBaseFee, + Preconditions: txnbuild.Preconditions{ + TimeBounds: txnbuild.NewInfiniteTimeout(), + }, + }) + + tx, err := txnbuild.NewTransaction(params) + require.NoError(t, err) + sendSuccessfulTransaction(t, client, sourceAccount, tx) + + params = preflightTransactionParams(t, client, txnbuild.TransactionParams{ + SourceAccount: &account, + IncrementSequenceNum: true, + Operations: []txnbuild.Operation{ + createCreateContractOperation(address, helloWorldContract), + }, + BaseFee: txnbuild.MinBaseFee, + Preconditions: txnbuild.Preconditions{ + TimeBounds: txnbuild.NewInfiniteTimeout(), + }, + }) + + tx, err = txnbuild.NewTransaction(params) + require.NoError(t, err) + sendSuccessfulTransaction(t, client, sourceAccount, tx) + + contractID := getContractID(t, address, testSalt, StandaloneNetworkPassphrase) + authAddrArg := "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H" + tx, err = txnbuild.NewTransaction(txnbuild.TransactionParams{ + SourceAccount: &account, + IncrementSequenceNum: true, + Operations: []txnbuild.Operation{ + &txnbuild.CreateAccount{ + Destination: authAddrArg, + Amount: "100000", + SourceAccount: address, + }, + }, + BaseFee: txnbuild.MinBaseFee, + Preconditions: txnbuild.Preconditions{ + TimeBounds: txnbuild.NewInfiniteTimeout(), + }, + }) + require.NoError(t, err) + sendSuccessfulTransaction(t, client, sourceAccount, tx) + + contractHash := sha256.Sum256(helloWorldContract) + byteSlice := xdr.ScBytes(contractHash[:]) + + params = txnbuild.TransactionParams{ + SourceAccount: &account, + IncrementSequenceNum: false, + Operations: []txnbuild.Operation{ + createInvokeHostOperation( + address, + contractID, + "upgrade_contract", + xdr.ScVal{ + Type: xdr.ScValTypeScvBytes, + Bytes: &byteSlice, + }, + ), + }, + BaseFee: txnbuild.MinBaseFee, + Preconditions: txnbuild.Preconditions{ + TimeBounds: txnbuild.NewInfiniteTimeout(), + }, + } + tx, err = txnbuild.NewTransaction(params) + + require.NoError(t, err) + + txB64, err := tx.Base64() + require.NoError(t, err) + + request := methods.SimulateTransactionRequest{Transaction: txB64} + var response methods.SimulateTransactionResponse + err = client.CallResult(context.Background(), "simulateTransaction", request, &response) + require.NoError(t, err) + require.Empty(t, response.Error) + + // check the result + require.Len(t, response.Results, 1) + var obtainedResult xdr.ScVal + err = xdr.SafeUnmarshalBase64(response.Results[0].XDR, &obtainedResult) + require.NoError(t, err) + + var transactionData xdr.SorobanTransactionData + err = xdr.SafeUnmarshalBase64(response.TransactionData, &transactionData) + require.NoError(t, err) + + assert.Equal(t, xdr.Int64(45), transactionData.RefundableFee) + assert.Equal(t, xdr.Uint32(7260), transactionData.Resources.ReadBytes) + assert.Equal(t, xdr.Uint32(104), transactionData.Resources.WriteBytes) + require.GreaterOrEqual(t, len(response.Events), 3) +} diff --git a/cmd/soroban-rpc/lib/preflight/src/fees.rs b/cmd/soroban-rpc/lib/preflight/src/fees.rs index 5018dac82..86d3a9b44 100644 --- a/cmd/soroban-rpc/lib/preflight/src/fees.rs +++ b/cmd/soroban-rpc/lib/preflight/src/fees.rs @@ -261,7 +261,9 @@ fn calculate_unmodified_ledger_entry_bytes( fn calculate_contract_events_size_bytes(events: &Vec) -> Result { let mut res: u32 = 0; for e in events { - if e.event.type_ != ContractEventType::Contract { + if e.event.type_ != ContractEventType::Contract + && e.event.type_ != ContractEventType::System + { continue; } let event_xdr = e