1616package vm_test
1717
1818import (
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