@@ -10,11 +10,13 @@ import (
1010 "math/big"
1111 "slices"
1212 "sort"
13+ "strings"
1314 "testing"
1415 "time"
1516
1617 "github.com/google/go-cmp/cmp"
1718
19+ "github.com/ethereum/go-ethereum"
1820 "github.com/ethereum/go-ethereum/accounts/abi/bind"
1921 "github.com/ethereum/go-ethereum/common"
2022 "github.com/ethereum/go-ethereum/core/types"
@@ -26,6 +28,7 @@ import (
2628 "github.com/offchainlabs/nitro/arbos/burn"
2729 "github.com/offchainlabs/nitro/arbos/l1pricing"
2830 "github.com/offchainlabs/nitro/cmd/chaininfo"
31+ "github.com/offchainlabs/nitro/gethhook"
2932 "github.com/offchainlabs/nitro/precompiles"
3033 "github.com/offchainlabs/nitro/solgen/go/localgen"
3134 "github.com/offchainlabs/nitro/solgen/go/precompilesgen"
@@ -1357,3 +1360,85 @@ func TestArbDebugOverwriteContractCode(t *testing.T) {
13571360 t .Fatal ("expected code B to be" , testCodeB , "got" , code )
13581361 }
13591362}
1363+
1364+ func TestDisableArbOwnerEthCall (t * testing.T ) {
1365+ ctx , cancel := context .WithCancel (context .Background ())
1366+ defer cancel ()
1367+
1368+ builder := NewNodeBuilder (ctx ).DefaultConfig (t , false ).DontParalellise ()
1369+ builder .execConfig .DisableArbOwnerEthCall = true
1370+ cleanup := builder .Build (t )
1371+ // The DisableArbOwnerEthCall flag is set on the global OwnerPrecompile singleton,
1372+ // so it persists across tests running in the same process. We must:
1373+ // 1. Not run in parallel (DontParalellise above) to avoid affecting concurrent tests
1374+ // 2. Reset the flag on cleanup to avoid affecting subsequent tests
1375+ defer func () {
1376+ gethhook .GetOwnerPrecompile ().SetDisableEthCall (false )
1377+ cleanup ()
1378+ }()
1379+
1380+ arbOwnerABI , err := precompilesgen .ArbOwnerMetaData .GetAbi ()
1381+ Require (t , err )
1382+ calldata , err := arbOwnerABI .Pack ("getAllChainOwners" )
1383+ Require (t , err )
1384+ arbOwnerAddr := types .ArbOwnerAddress
1385+
1386+ expectedErrMsg := "ArbOwner precompile is disabled outside on-chain execution"
1387+
1388+ // eth_call should fail
1389+ _ , err = builder .L2 .Client .CallContract (ctx , ethereum.CallMsg {
1390+ To : & arbOwnerAddr ,
1391+ Data : calldata ,
1392+ }, nil )
1393+ if err == nil || ! strings .Contains (err .Error (), expectedErrMsg ) {
1394+ Fatal (t , "eth_call to ArbOwner expected error containing" , expectedErrMsg , "got" , err )
1395+ }
1396+
1397+ // eth_estimateGas should fail
1398+ _ , err = builder .L2 .Client .EstimateGas (ctx , ethereum.CallMsg {
1399+ To : & arbOwnerAddr ,
1400+ Data : calldata ,
1401+ })
1402+ if err == nil || ! strings .Contains (err .Error (), expectedErrMsg ) {
1403+ Fatal (t , "eth_estimateGas to ArbOwner expected error containing" , expectedErrMsg , "got" , err )
1404+ }
1405+
1406+ // On-chain transaction should still succeed
1407+ auth := builder .L2Info .GetDefaultTransactOpts ("Owner" , ctx )
1408+ auth .GasLimit = 32_000_000
1409+ arbOwner , err := precompilesgen .NewArbOwner (arbOwnerAddr , builder .L2 .Client )
1410+ Require (t , err )
1411+ tx , err := arbOwner .AddChainOwner (& auth , common .HexToAddress ("0xdeadbeef" ))
1412+ Require (t , err )
1413+ _ , err = builder .L2 .EnsureTxSucceeded (tx )
1414+ Require (t , err )
1415+ }
1416+
1417+ func TestArbOwnerEthCallEnabled (t * testing.T ) {
1418+ ctx , cancel := context .WithCancel (context .Background ())
1419+ defer cancel ()
1420+
1421+ builder := NewNodeBuilder (ctx ).DefaultConfig (t , false ).DontParalellise ()
1422+ cleanup := builder .Build (t )
1423+ defer cleanup ()
1424+
1425+ arbOwnerABI , err := precompilesgen .ArbOwnerMetaData .GetAbi ()
1426+ Require (t , err )
1427+ calldata , err := arbOwnerABI .Pack ("getAllChainOwners" )
1428+ Require (t , err )
1429+ arbOwnerAddr := types .ArbOwnerAddress
1430+
1431+ // eth_call should succeed when DisableArbOwnerEthCall is false (default)
1432+ _ , err = builder .L2 .Client .CallContract (ctx , ethereum.CallMsg {
1433+ To : & arbOwnerAddr ,
1434+ Data : calldata ,
1435+ }, nil )
1436+ Require (t , err )
1437+
1438+ // eth_estimateGas should succeed when DisableArbOwnerEthCall is false (default)
1439+ _ , err = builder .L2 .Client .EstimateGas (ctx , ethereum.CallMsg {
1440+ To : & arbOwnerAddr ,
1441+ Data : calldata ,
1442+ })
1443+ Require (t , err )
1444+ }
0 commit comments