From d5704c0702cad76d2895a02f1376e22b96a2f540 Mon Sep 17 00:00:00 2001 From: JaredBorders Date: Tue, 3 Oct 2023 18:39:34 -0400 Subject: [PATCH] add diff --- diff.patch | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 diff.patch diff --git a/diff.patch b/diff.patch new file mode 100644 index 0000000..54b2de6 --- /dev/null +++ b/diff.patch @@ -0,0 +1,163 @@ +diff --git a/src/SMv2SessionValidationModule.sol b/src/SMv2SessionValidationModule.sol +index f8d6e03..916aabc 100644 +--- a/src/SMv2SessionValidationModule.sol ++++ b/src/SMv2SessionValidationModule.sol +@@ -1,11 +1,9 @@ +-// SPDX-License-Identifier: GPL-3.0-or-later +-pragma solidity 0.8.18; ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.17; + +-import { +- ISessionValidationModule, +- UserOperation +-} from "src/biconomy/interfaces/ISessionValidationModule.sol"; +-import {ECDSA} from "src/openzeppelin/ECDSA.sol"; ++import {ISessionValidationModule, UserOperation} from ++ "src/interfaces/ISessionValidationModule.sol"; ++// import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; + + /** + * @title Kwenta Smart Margin v2 Session Validation Module for Biconomy Smart Accounts. +@@ -13,12 +11,8 @@ import {ECDSA} from "src/openzeppelin/ECDSA.sol"; + * @author Fil Makarov - + * @author JaredBorders (jaredborders@pm.me) + */ +-contract SMv2SessionValidationModule is ISessionValidationModule { +- error InvalidSelector(); +- error InvalidSMv2Selector(); +- error InvalidDestinationContract(); +- error InvalidCallValue(); + ++contract SMv2SessionValidationModule is ISessionValidationModule { + /** + * @dev validates that the call (destinationContract, callValue, funcCallData) + * complies with the Session Key permissions represented by sessionKeyData +@@ -36,32 +30,19 @@ contract SMv2SessionValidationModule is ISessionValidationModule { + ) external virtual override returns (address) { + ( + address sessionKey, +- address smv2ProxyAccount, +- bytes4 smv2ExecuteSelector +- ) = abi.decode(_sessionKeyData, (address, address, bytes4)); +- +- /// @dev ensure destinationContract is the SMv2ProxyAccount +- if (destinationContract != smv2ProxyAccount) { +- revert InvalidDestinationContract(); +- } +- +- /// @dev ensure the function selector is the `SmartAccount.execute` selector +- if (bytes4(_funcCallData[0:4]) != smv2ExecuteSelector) { +- revert InvalidSMv2Selector(); +- } +- +- /// @dev ensure call value is zero +- if (callValue != 0) { +- revert InvalidCallValue(); +- } ++ address token, ++ address recipient, ++ uint256 maxAmount ++ ) = abi.decode(_sessionKeyData, (address, address, address, uint256)); + +- // (IAccount.Command[] memory _commands, bytes[] memory _inputs) = abi.decode( +- // _funcCallData[4:], +- // (IAccount.Command[], bytes[]) +- // ); ++ require(destinationContract == token, "ERC20SV Invalid Token"); ++ require(callValue == 0, "ERC20SV Non Zero Value"); + +- /// @custom:add-param-validation-here-if-needed ++ (address recipientCalled, uint256 amount) = ++ abi.decode(_funcCallData[4:], (address, uint256)); + ++ require(recipient == recipientCalled, "ERC20SV Wrong Recipient"); ++ require(amount <= maxAmount, "ERC20SV Max Amount Exceeded"); + return sessionKey; + } + +@@ -81,58 +62,53 @@ contract SMv2SessionValidationModule is ISessionValidationModule { + bytes calldata _sessionKeyData, + bytes calldata _sessionKeySignature + ) external pure override returns (bool) { +- /// @dev ensure function selector is `IAccount.execute` +- if ( +- bytes4(_op.callData[0:4]) != EXECUTE_SELECTOR +- && bytes4(_op.callData[0:4]) != EXECUTE_OPTIMIZED_SELECTOR +- ) { +- revert InvalidSelector(); +- } ++ require( ++ bytes4(_op.callData[0:4]) == EXECUTE_OPTIMIZED_SELECTOR ++ || bytes4(_op.callData[0:4]) == EXECUTE_SELECTOR, ++ "ERC20SV Invalid Selector" ++ ); + + ( + address sessionKey, +- address smv2ProxyAccount, +- bytes4 smv2ExecuteSelector +- ) = abi.decode(_sessionKeyData, (address, address, bytes4)); ++ address token, ++ address recipient, ++ uint256 maxAmount ++ ) = abi.decode(_sessionKeyData, (address, address, address, uint256)); + + { + // we expect _op.callData to be `SmartAccount.execute(to, value, calldata)` calldata +- (address destinationContract, uint256 callValue,) = abi.decode( ++ (address tokenAddr, uint256 callValue,) = abi.decode( + _op.callData[4:], // skip selector + (address, uint256, bytes) + ); +- +- /// @dev ensure destinationContract is the SMv2ProxyAccount +- if (destinationContract != smv2ProxyAccount) { +- revert InvalidDestinationContract(); ++ if (tokenAddr != token) { ++ revert("ERC20SV Wrong Token"); + } +- +- /// @dev ensure call value is zero + if (callValue != 0) { +- revert InvalidCallValue(); ++ revert("ERC20SV Non Zero Value"); + } + } +- + // working with userOp.callData +- // check if the call is conforms to `IAccount.execute` ++ // check if the call is to the allowed recepient and amount is not more than allowed + bytes calldata data; + { + uint256 offset = uint256(bytes32(_op.callData[4 + 64:4 + 96])); + uint256 length = + uint256(bytes32(_op.callData[4 + offset:4 + offset + 32])); +- // we expect data to be the `IAccount.execute(Command[] _commands, bytes[] _inputs)` calldata ++ //we expect data to be the `IERC20.transfer(address, uint256)` calldata + data = _op.callData[4 + offset + 32:4 + offset + 32 + length]; + } +- +- /// @dev ensure the function selector is the smv2ExecuteSelector selector +- if (bytes4(data[0:4]) != smv2ExecuteSelector) { +- revert InvalidSMv2Selector(); ++ if (address(bytes20(data[16:36])) != recipient) { ++ revert("ERC20SV Wrong Recipient"); + } +- +- /// @dev this method of signature validation is out-of-date +- /// see https://github.com/OpenZeppelin/openzeppelin-sdk/blob/7d96de7248ae2e7e81a743513ccc617a2e6bba21/packages/lib/contracts/cryptography/ECDSA.sol#L6 +- return ECDSA.recover( +- ECDSA.toEthSignedMessageHash(_userOpHash), _sessionKeySignature +- ) == sessionKey; ++ if (uint256(bytes32(data[36:68])) > maxAmount) { ++ revert("ERC20SV Max Amount Exceeded"); ++ } ++ return ++ // ECDSA.recover( ++ // ECDSA.toEthSignedMessageHash(_userOpHash), ++ // _sessionKeySignature ++ // ) == sessionKey; ++ true; + } + }