diff --git a/arbitrator/prover/src/programs/meter.rs b/arbitrator/prover/src/programs/meter.rs index ab069fd911..4abcbcad40 100644 --- a/arbitrator/prover/src/programs/meter.rs +++ b/arbitrator/prover/src/programs/meter.rs @@ -246,6 +246,10 @@ pub trait MeteredMachine { } fn out_of_ink(&mut self) -> Result { + println!( + "Got out of ink in rust at:\n{}", + std::backtrace::Backtrace::force_capture() + ); self.set_meter(MachineMeter::Exhausted); Err(OutOfInkError) } diff --git a/arbitrator/stylus/tests/multicall/Cargo.toml b/arbitrator/stylus/tests/multicall/Cargo.toml index 3bc48c6826..ec84ace7b4 100644 --- a/arbitrator/stylus/tests/multicall/Cargo.toml +++ b/arbitrator/stylus/tests/multicall/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" alloy-primitives = "0.3.1" alloy-sol-types = "0.3.1" mini-alloc = "0.4.2" -stylus-sdk = { path = "../../../langs/rust/stylus-sdk", features = ["reentrant"] } +stylus-sdk = { path = "../../../langs/rust/stylus-sdk", features = ["reentrant", "debug"] } hex = "0.4.3" wee_alloc = "0.4.5" diff --git a/arbitrator/stylus/tests/multicall/src/main.rs b/arbitrator/stylus/tests/multicall/src/main.rs index fd6929b8f1..86c5ecb1ab 100644 --- a/arbitrator/stylus/tests/multicall/src/main.rs +++ b/arbitrator/stylus/tests/multicall/src/main.rs @@ -6,13 +6,12 @@ extern crate alloc; use stylus_sdk::{ - storage::{StorageCache, GlobalStorage}, alloy_primitives::{Address, B256}, alloy_sol_types::sol, call::RawCall, - console, - evm, + console, evm, prelude::*, + storage::{GlobalStorage, StorageCache}, }; use wee_alloc::WeeAlloc; @@ -20,7 +19,7 @@ use wee_alloc::WeeAlloc; #[global_allocator] static ALLOC: WeeAlloc = WeeAlloc::INIT; -sol!{ +sol! { event Called(address addr, uint8 count, bool success, bytes return_data); event Storage(bytes32 slot, bytes32 data, bool write); } @@ -74,20 +73,31 @@ fn user_main(input: Vec) -> Result, Vec> { Ok(return_data) => (true, return_data), Err(revert_data) => { if kind & 0x4 == 0 { - return Err(revert_data) + console!( + "Contract {addr} errored with {} and kind matchhing 0x4", + revert_data.len() + ); + return Err(revert_data); } (false, vec![]) - }, + } }; - + if !return_data.is_empty() { console!("Contract {addr} returned {} bytes", return_data.len()); + } else { + console!("Contract {addr} returned no data"); } if kind & 0x8 != 0 { - evm::log(Called { addr, count, success, return_data: return_data.clone() }) + evm::log(Called { + addr, + count, + success, + return_data: return_data.clone(), + }) } output.extend(return_data); - } else if kind & 0xf0 == 0x10 { + } else if kind & 0xf0 == 0x10 { // storage let slot = B256::try_from(&curr[..32]).unwrap(); curr = &curr[32..]; @@ -99,7 +109,7 @@ fn user_main(input: Vec) -> Result, Vec> { write = true; unsafe { StorageCache::set_word(slot.into(), data.into()) }; StorageCache::flush(); - } else if kind & 0x7 == 1{ + } else if kind & 0x7 == 1 { console!("reading slot"); write = false; data = StorageCache::get_word(slot.into()); @@ -109,7 +119,11 @@ fn user_main(input: Vec) -> Result, Vec> { } if kind & 0x8 != 0 { console!("slot: {}, data: {}, write {write}", slot, data); - evm::log(Storage { slot: slot.into(), data: data.into(), write }) + evm::log(Storage { + slot: slot.into(), + data: data.into(), + write, + }) } } else { panic!("unknown action {kind}") diff --git a/arbos/programs/api.go b/arbos/programs/api.go index 0519cd9f01..d06529b45d 100644 --- a/arbos/programs/api.go +++ b/arbos/programs/api.go @@ -5,6 +5,8 @@ package programs import ( "errors" + "fmt" + "runtime/debug" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -209,6 +211,7 @@ func newApiClosures( baseCost = am.SaturatingUAdd(baseCost, keccakCost) } if gas < baseCost { + fmt.Printf("got out of gas at:\n%v\n", string(debug.Stack())) return zeroAddr, nil, gas, vm.ErrOutOfGas } gas -= baseCost diff --git a/arbos/programs/programs.go b/arbos/programs/programs.go index 12102bac84..0b7d550e4f 100644 --- a/arbos/programs/programs.go +++ b/arbos/programs/programs.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "math/big" + "runtime/debug" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -210,6 +211,7 @@ func (p Programs) CallProgram( callCost = am.SaturatingUAdd(callCost, program.initGas(params)) } if err := contract.BurnGas(callCost); err != nil { + fmt.Printf("got out of gas at:\n%v\n", string(debug.Stack())) return nil, err } statedb.AddStylusPages(program.footprint) @@ -253,6 +255,7 @@ func (p Programs) CallProgram( evmCost := evmMemoryCost(uint64(len(ret))) if startingGas < evmCost { contract.Gas = 0 + fmt.Printf("got out of gas at:\n%v\n", string(debug.Stack())) return nil, vm.ErrOutOfGas } maxGasToReturn := startingGas - evmCost @@ -552,7 +555,7 @@ const ( userOutOfStack ) -func (status userStatus) toResult(data []byte, debug bool) ([]byte, string, error) { +func (status userStatus) toResult(data []byte, _ bool) ([]byte, string, error) { msg := arbutil.ToStringOrHex(data) switch status { case userSuccess: @@ -562,6 +565,7 @@ func (status userStatus) toResult(data []byte, debug bool) ([]byte, string, erro case userFailure: return nil, msg, vm.ErrExecutionReverted case userOutOfInk: + fmt.Printf("got out of gas at:\n%v\n", string(debug.Stack())) return nil, "", vm.ErrOutOfGas case userOutOfStack: return nil, "", vm.ErrDepth diff --git a/system_tests/program_test.go b/system_tests/program_test.go index 31b27733e8..b0aa97228d 100644 --- a/system_tests/program_test.go +++ b/system_tests/program_test.go @@ -960,7 +960,6 @@ func testMemory(t *testing.T, jit bool) { l2info := builder.L2Info l2client := builder.L2.Client l2rpc := l2client.Client() - defer l2rpc.Close() defer cleanup() trace := func(ctx context.Context, tx *types.Transaction) error { @@ -995,7 +994,7 @@ func testMemory(t *testing.T, jit bool) { Require(t, err) ensure(arbOwner.SetInkPrice(&auth, 1e4)) - ensure(arbOwner.SetMaxTxGasLimit(&auth, 34000000)) + ensure(arbOwner.SetMaxTxGasLimit(&auth, 1e9)) memoryAddr := deployWasm(t, ctx, auth, l2client, watFile("memory")) multiAddr := deployWasm(t, ctx, auth, l2client, rustFile("multicall")) @@ -1553,6 +1552,11 @@ func readWasmFile(t *testing.T, file string) ([]byte, []byte) { wasm, err := arbcompress.Compress(wasmSource, arbcompress.LEVEL_WELL, randDict) Require(t, err) + if name == "memory" { + colors.PrintGrey(fmt.Sprintf("memory randDict: %v", randDict)) + colors.PrintGrey(fmt.Sprintf("memory wasmHash: %v", crypto.Keccak256Hash(wasm))) + } + toKb := func(data []byte) float64 { return float64(len(data)) / 1024.0 } colors.PrintGrey(fmt.Sprintf("%v: len %.2fK vs %.2fK", name, toKb(wasm), toKb(wasmSource)))