Skip to content

Commit e8101dc

Browse files
committed
test: vm.WithUNSAFECallerAddressProxying() effect on outgoing caller addr
1 parent 55ab72c commit e8101dc

File tree

1 file changed

+74
-12
lines changed

1 file changed

+74
-12
lines changed

core/vm/contracts.libevm_test.go

Lines changed: 74 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package vm_test
1717

1818
import (
19+
"bytes"
1920
"fmt"
2021
"math/big"
2122
"reflect"
@@ -375,10 +376,12 @@ func makeReturnProxy(t *testing.T, dest common.Address, call vm.OpCode) []vm.OpC
375376
t.Helper()
376377
const p0 = vm.PUSH0
377378
contract := []vm.OpCode{
378-
vm.PUSH1, 1, // retSize (bytes)
379-
p0, // retOffset
380-
p0, // argSize
381-
p0, // argOffset
379+
vm.CALLDATASIZE, p0, p0, vm.CALLDATACOPY,
380+
381+
p0, // retSize
382+
p0, // retOffset
383+
vm.CALLDATASIZE, // argSize
384+
p0, // argOffset
382385
}
383386

384387
// See CALL signature: https://www.evm.codes/#f1?fork=cancun
@@ -511,13 +514,21 @@ func TestPrecompileMakeCall(t *testing.T) {
511514
dest := common.HexToAddress("DE57")
512515

513516
rng := ethtest.NewPseudoRand(142857)
514-
callData := rng.Bytes(8)
517+
precompileCallData := rng.Bytes(8)
518+
519+
// If the SUT precompile receives this as its calldata then it will use the
520+
// vm.WithUNSAFECallerAddressProxying() option.
521+
unsafeCallerProxyOptSentinel := []byte("override-caller sentinel")
515522

516523
hooks := &hookstest.Stub{
517524
PrecompileOverrides: map[common.Address]libevm.PrecompiledContract{
518525
sut: vm.NewStatefulPrecompile(func(env vm.PrecompileEnvironment, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) {
526+
var opts []vm.CallOption
527+
if bytes.Equal(input, unsafeCallerProxyOptSentinel) {
528+
opts = append(opts, vm.WithUNSAFECallerAddressProxying())
529+
}
519530
// We are ultimately testing env.Call(), hence why this is the SUT.
520-
return env.Call(dest, callData, suppliedGas, uint256.NewInt(0))
531+
return env.Call(dest, precompileCallData, suppliedGas, uint256.NewInt(0), opts...)
521532
}),
522533
dest: vm.NewStatefulPrecompile(func(env vm.PrecompileEnvironment, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) {
523534
out := &statefulPrecompileOutput{
@@ -538,6 +549,7 @@ func TestPrecompileMakeCall(t *testing.T) {
538549

539550
tests := []struct {
540551
incomingCallType vm.OpCode
552+
eoaTxCallData []byte
541553
// Unlike TestNewStatefulPrecompile, which tests the AddressContext of
542554
// the precompile itself, these test the AddressContext of a contract
543555
// called by the precompile.
@@ -551,7 +563,19 @@ func TestPrecompileMakeCall(t *testing.T) {
551563
Caller: sut,
552564
Self: dest,
553565
},
554-
Input: callData,
566+
Input: precompileCallData,
567+
},
568+
},
569+
{
570+
incomingCallType: vm.CALL,
571+
eoaTxCallData: unsafeCallerProxyOptSentinel,
572+
want: statefulPrecompileOutput{
573+
Addresses: &libevm.AddressContext{
574+
Origin: eoa,
575+
Caller: caller, // overridden by CallOption
576+
Self: dest,
577+
},
578+
Input: precompileCallData,
555579
},
556580
},
557581
{
@@ -562,7 +586,19 @@ func TestPrecompileMakeCall(t *testing.T) {
562586
Caller: caller, // SUT runs as its own caller because of CALLCODE
563587
Self: dest,
564588
},
565-
Input: callData,
589+
Input: precompileCallData,
590+
},
591+
},
592+
{
593+
incomingCallType: vm.CALLCODE,
594+
eoaTxCallData: unsafeCallerProxyOptSentinel,
595+
want: statefulPrecompileOutput{
596+
Addresses: &libevm.AddressContext{
597+
Origin: eoa,
598+
Caller: caller, // CallOption is a NOOP
599+
Self: dest,
600+
},
601+
Input: precompileCallData,
566602
},
567603
},
568604
{
@@ -573,7 +609,19 @@ func TestPrecompileMakeCall(t *testing.T) {
573609
Caller: caller, // as with CALLCODE
574610
Self: dest,
575611
},
576-
Input: callData,
612+
Input: precompileCallData,
613+
},
614+
},
615+
{
616+
incomingCallType: vm.DELEGATECALL,
617+
eoaTxCallData: unsafeCallerProxyOptSentinel,
618+
want: statefulPrecompileOutput{
619+
Addresses: &libevm.AddressContext{
620+
Origin: eoa,
621+
Caller: caller, // CallOption is a NOOP
622+
Self: dest,
623+
},
624+
Input: precompileCallData,
577625
},
578626
},
579627
{
@@ -584,25 +632,39 @@ func TestPrecompileMakeCall(t *testing.T) {
584632
Caller: sut,
585633
Self: dest,
586634
},
587-
Input: callData,
635+
Input: precompileCallData,
588636
// This demonstrates that even though the precompile makes a
589637
// (non-static) CALL, the read-only state is inherited. Yes,
590638
// this is _another_ way to get a read-only state, different to
591639
// the other tests.
592640
ReadOnly: true,
593641
},
594642
},
643+
{
644+
incomingCallType: vm.STATICCALL,
645+
eoaTxCallData: unsafeCallerProxyOptSentinel,
646+
want: statefulPrecompileOutput{
647+
Addresses: &libevm.AddressContext{
648+
Origin: eoa,
649+
Caller: caller, // overridden by CallOption
650+
Self: dest,
651+
},
652+
Input: precompileCallData,
653+
ReadOnly: true,
654+
},
655+
},
595656
}
596657

597658
for _, tt := range tests {
598-
t.Run(fmt.Sprintf("via %s", tt.incomingCallType), func(t *testing.T) {
659+
t.Run(tt.incomingCallType.String(), func(t *testing.T) {
660+
t.Logf("calldata = %q", tt.eoaTxCallData)
599661
state, evm := ethtest.NewZeroEVM(t)
600662
evm.Origin = eoa
601663
state.CreateAccount(caller)
602664
proxy := makeReturnProxy(t, sut, tt.incomingCallType)
603665
state.SetCode(caller, convertBytes[vm.OpCode, byte](proxy))
604666

605-
got, _, err := evm.Call(vm.AccountRef(eoa), caller, nil, 1e6, uint256.NewInt(0))
667+
got, _, err := evm.Call(vm.AccountRef(eoa), caller, tt.eoaTxCallData, 1e6, uint256.NewInt(0))
606668
require.NoError(t, err)
607669
require.Equal(t, tt.want.String(), string(got))
608670
})

0 commit comments

Comments
 (0)