diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 8d91df5482..2b9a58931b 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1941,6 +1941,33 @@ func (s *TransactionAPI) SendRawTransaction(ctx context.Context, input hexutil.B return SubmitTransaction(ctx, s.b, tx) } +type mevmStateLogger struct { + hasStoredState bool +} + +func (m *mevmStateLogger) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { +} + +func (m *mevmStateLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { + if op == vm.SSTORE { + m.hasStoredState = true + } +} + +func (m *mevmStateLogger) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) { +} + +func (m *mevmStateLogger) CaptureEnd(output []byte, gasUsed uint64, err error) {} + +func (m *mevmStateLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { +} + +func (m *mevmStateLogger) CaptureExit(output []byte, gasUsed uint64, err error) {} + +func (m *mevmStateLogger) CaptureTxStart(gasLimit uint64) {} + +func (m *mevmStateLogger) CaptureTxEnd(restGas uint64) {} + // TODO: should be its own api func runMEVM(ctx context.Context, b Backend, state *state.StateDB, header *types.Header, tx *types.Transaction, msg *core.Message, isCall bool) (*types.Transaction, *core.ExecutionResult, func() error, error) { var cancel context.CancelFunc @@ -1960,9 +1987,11 @@ func runMEVM(ctx context.Context, b Backend, state *state.StateDB, header *types return nil, nil, nil, err } + storageAccessTracer := &mevmStateLogger{} + blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil) suaveCtx := b.SuaveContext(tx, confidentialRequest) - evm, storeFinalize, vmError := b.GetMEVM(ctx, msg, state, header, &vm.Config{IsConfidential: true, NoBaseFee: isCall}, &blockCtx, &suaveCtx) + evm, storeFinalize, vmError := b.GetMEVM(ctx, msg, state, header, &vm.Config{IsConfidential: true, NoBaseFee: isCall, Tracer: storageAccessTracer}, &blockCtx, &suaveCtx) // Wait for the context to be done and cancel the evm. Even if the // EVM has finished, cancelling may be done (repeatedly) @@ -1991,6 +2020,10 @@ func runMEVM(ctx context.Context, b Backend, state *state.StateDB, header *types return nil, nil, nil, fmt.Errorf("%w: %s", result.Err, hexutil.Encode(result.Revert())) } + if storageAccessTracer.hasStoredState { + return nil, nil, nil, fmt.Errorf("confidential request cannot modify state storage") + } + // Check for call in return var computeResult []byte diff --git a/suave/artifacts/example.sol/ExampleEthCallSource.json b/suave/artifacts/example.sol/ExampleEthCallSource.json index fa5d8e5027..75f1631f5a 100644 --- a/suave/artifacts/example.sol/ExampleEthCallSource.json +++ b/suave/artifacts/example.sol/ExampleEthCallSource.json @@ -33,12 +33,19 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [], + "name": "ilegalStateTransition", + "outputs": [], + "stateMutability": "payable", + "type": "function" } ], "deployedBytecode": { - "object": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c806348bce06414610030575b600080fd5b61004361003e366004610183565b610045565b005b6040805160048152602481019091526020810180516001600160e01b0316631b53398f60e21b17905260009061007c9084906100b2565b905060008180602001905181019061009491906101bb565b67ffffffffffffffff1690508281146100ac57600080fd5b50505050565b606060008063421000036001600160a01b031685856040516020016100d8929190610210565b60408051601f19818403018152908290526100f291610252565b600060405180830381855afa9150503d806000811461012d576040519150601f19603f3d011682016040523d82523d6000602084013e610132565b606091505b509150915081610166576342100003816040516375fff46760e01b815260040161015d929190610210565b60405180910390fd5b8080602001905181019061017a9190610284565b95945050505050565b6000806040838503121561019657600080fd5b82356001600160a01b03811681146101ad57600080fd5b946020939093013593505050565b6000602082840312156101cd57600080fd5b815167ffffffffffffffff811681146101e557600080fd5b9392505050565b60005b838110156102075781810151838201526020016101ef565b50506000910152565b60018060a01b0383168152604060208201526000825180604084015261023d8160608501602087016101ec565b601f01601f1916919091016060019392505050565b600082516102648184602087016101ec565b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561029657600080fd5b815167ffffffffffffffff808211156102ae57600080fd5b818401915084601f8301126102c257600080fd5b8151818111156102d4576102d461026e565b604051601f8201601f19908116603f011681019083821181831017156102fc576102fc61026e565b8160405282815287602084870101111561031557600080fd5b6103268360208301602088016101ec565b97965050505050505056fea164736f6c6343000813000a" + "object": "0x6080604052600436106100295760003560e01c806348bce0641461002e5780639476e96614610050575b600080fd5b34801561003a57600080fd5b5061004e6100493660046101d8565b610058565b005b61004e6100c5565b6040805160048152602481019091526020810180516001600160e01b0316631b53398f60e21b17905260009061008f908490610107565b90506000818060200190518101906100a79190610210565b67ffffffffffffffff1690508281146100bf57600080fd5b50505050565b6000805467ffffffffffffffff1690806100de83610241565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b606060008063421000036001600160a01b0316858560405160200161012d92919061029a565b60408051601f1981840301815290829052610147916102dc565b600060405180830381855afa9150503d8060008114610182576040519150601f19603f3d011682016040523d82523d6000602084013e610187565b606091505b5091509150816101bb576342100003816040516375fff46760e01b81526004016101b292919061029a565b60405180910390fd5b808060200190518101906101cf919061030e565b95945050505050565b600080604083850312156101eb57600080fd5b82356001600160a01b038116811461020257600080fd5b946020939093013593505050565b60006020828403121561022257600080fd5b815167ffffffffffffffff8116811461023a57600080fd5b9392505050565b600067ffffffffffffffff80831681810361026c57634e487b7160e01b600052601160045260246000fd5b6001019392505050565b60005b83811015610291578181015183820152602001610279565b50506000910152565b60018060a01b038316815260406020820152600082518060408401526102c7816060850160208701610276565b601f01601f1916919091016060019392505050565b600082516102ee818460208701610276565b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561032057600080fd5b815167ffffffffffffffff8082111561033857600080fd5b818401915084601f83011261034c57600080fd5b81518181111561035e5761035e6102f8565b604051601f8201601f19908116603f01168101908382118183101715610386576103866102f8565b8160405282815287602084870101111561039f57600080fd5b6103b0836020830160208801610276565b97965050505050505056fea164736f6c6343000813000a" }, "bytecode": { - "object": "0x608060405234801561001057600080fd5b5061033e806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806348bce06414610030575b600080fd5b61004361003e366004610183565b610045565b005b6040805160048152602481019091526020810180516001600160e01b0316631b53398f60e21b17905260009061007c9084906100b2565b905060008180602001905181019061009491906101bb565b67ffffffffffffffff1690508281146100ac57600080fd5b50505050565b606060008063421000036001600160a01b031685856040516020016100d8929190610210565b60408051601f19818403018152908290526100f291610252565b600060405180830381855afa9150503d806000811461012d576040519150601f19603f3d011682016040523d82523d6000602084013e610132565b606091505b509150915081610166576342100003816040516375fff46760e01b815260040161015d929190610210565b60405180910390fd5b8080602001905181019061017a9190610284565b95945050505050565b6000806040838503121561019657600080fd5b82356001600160a01b03811681146101ad57600080fd5b946020939093013593505050565b6000602082840312156101cd57600080fd5b815167ffffffffffffffff811681146101e557600080fd5b9392505050565b60005b838110156102075781810151838201526020016101ef565b50506000910152565b60018060a01b0383168152604060208201526000825180604084015261023d8160608501602087016101ec565b601f01601f1916919091016060019392505050565b600082516102648184602087016101ec565b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561029657600080fd5b815167ffffffffffffffff808211156102ae57600080fd5b818401915084601f8301126102c257600080fd5b8151818111156102d4576102d461026e565b604051601f8201601f19908116603f011681019083821181831017156102fc576102fc61026e565b8160405282815287602084870101111561031557600080fd5b6103268360208301602088016101ec565b97965050505050505056fea164736f6c6343000813000a" + "object": "0x608060405234801561001057600080fd5b506103c8806100206000396000f3fe6080604052600436106100295760003560e01c806348bce0641461002e5780639476e96614610050575b600080fd5b34801561003a57600080fd5b5061004e6100493660046101d8565b610058565b005b61004e6100c5565b6040805160048152602481019091526020810180516001600160e01b0316631b53398f60e21b17905260009061008f908490610107565b90506000818060200190518101906100a79190610210565b67ffffffffffffffff1690508281146100bf57600080fd5b50505050565b6000805467ffffffffffffffff1690806100de83610241565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b606060008063421000036001600160a01b0316858560405160200161012d92919061029a565b60408051601f1981840301815290829052610147916102dc565b600060405180830381855afa9150503d8060008114610182576040519150601f19603f3d011682016040523d82523d6000602084013e610187565b606091505b5091509150816101bb576342100003816040516375fff46760e01b81526004016101b292919061029a565b60405180910390fd5b808060200190518101906101cf919061030e565b95945050505050565b600080604083850312156101eb57600080fd5b82356001600160a01b038116811461020257600080fd5b946020939093013593505050565b60006020828403121561022257600080fd5b815167ffffffffffffffff8116811461023a57600080fd5b9392505050565b600067ffffffffffffffff80831681810361026c57634e487b7160e01b600052601160045260246000fd5b6001019392505050565b60005b83811015610291578181015183820152602001610279565b50506000910152565b60018060a01b038316815260406020820152600082518060408401526102c7816060850160208701610276565b601f01601f1916919091016060019392505050565b600082516102ee818460208701610276565b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561032057600080fd5b815167ffffffffffffffff8082111561033857600080fd5b818401915084601f83011261034c57600080fd5b81518181111561035e5761035e6102f8565b604051601f8201601f19908116603f01168101908382118183101715610386576103866102f8565b8160405282815287602084870101111561039f57600080fd5b6103b0836020830160208801610276565b97965050505050505056fea164736f6c6343000813000a" } } diff --git a/suave/e2e/workflow_test.go b/suave/e2e/workflow_test.go index eb6980d5ce..716a575ee6 100644 --- a/suave/e2e/workflow_test.go +++ b/suave/e2e/workflow_test.go @@ -1100,6 +1100,21 @@ func TestE2EKettleAddressEndpoint(t *testing.T) { require.NotEmpty(t, addrs) } +func TestE2EOnChainStateTransition(t *testing.T) { + // This end-to-end tests that the callx precompile gets called from a confidential request + fr := newFramework(t) + defer fr.Close() + + clt := fr.NewSDKClient() + + contractAddr := common.Address{0x3} + sourceContract := sdk.GetContract(contractAddr, exampleCallSourceContract.Abi, clt) + + // a confidential request cannot make a state change + _, err := sourceContract.SendTransaction("ilegalStateTransition", []interface{}{}, nil) + require.Error(t, err) +} + type clientWrapper struct { t *testing.T diff --git a/suave/sol/standard_peekers/example.sol b/suave/sol/standard_peekers/example.sol index 7a1906e1f6..3564f17623 100644 --- a/suave/sol/standard_peekers/example.sol +++ b/suave/sol/standard_peekers/example.sol @@ -3,11 +3,17 @@ pragma solidity ^0.8.8; import "../libraries/Suave.sol"; contract ExampleEthCallSource { + uint64 state; + function callTarget(address target, uint256 expected) public { bytes memory output = Suave.ethcall(target, abi.encodeWithSignature("get()")); (uint256 num) = abi.decode(output, (uint64)); require(num == expected); } + + function ilegalStateTransition() public payable { + state++; + } } contract ExampleEthCallTarget {