From 699d481d86305d32c5643547b73a7360b15c3316 Mon Sep 17 00:00:00 2001 From: mevtxn Date: Thu, 21 Nov 2024 18:52:08 +0530 Subject: [PATCH 1/8] feat: bytes-params-changed-to-structs-in-laminator --- src/lamination/LaminatedProxy.sol | 11 +++++----- src/lamination/Laminator.sol | 36 +++++++++++++++---------------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/lamination/LaminatedProxy.sol b/src/lamination/LaminatedProxy.sol index f5121ac..8414836 100644 --- a/src/lamination/LaminatedProxy.sol +++ b/src/lamination/LaminatedProxy.sol @@ -156,10 +156,9 @@ contract LaminatedProxy is LaminatedStorage, ReentrancyGuard { /// @notice Executes a function call immediately. /// @dev Decodes the provided `input` into a CallObject and then calls `_execute`. /// Can only be invoked by the owner of the contract. - /// @param input The encoded CallObject containing information about the function call to execute. + /// @param callObjs The CallObjects containing information about the function call to execute. /// @return returnValue The return value from the executed function call. - function execute(bytes calldata input) external onlyOwner nonReentrant returns (bytes memory) { - CallObject[] memory callsToMake = abi.decode(input, (CallObject[])); + function execute(CallObject[] calldata callObjs) external onlyOwner nonReentrant returns (bytes memory) { return _executeAll(callsToMake); } @@ -215,17 +214,17 @@ contract LaminatedProxy is LaminatedStorage, ReentrancyGuard { /// @dev Adds a new CallObject to the `deferredCalls` mapping and emits a CallPushed event. /// The function can only be called by the Laminator or the LaminatedProxy contract itself. /// It can also be called re-entrantly to enable the contract to do cronjobs with tail recursion. - /// @param input The encoded CallObject containing information about the function call to defer. + /// @param callObjs The CallObjects containing information about the function call to defer. /// @param delay The number of blocks to delay before the function call can be executed. /// @param data Additional data to be associated with the sequence of call objs /// @return callSequenceNumber The sequence number assigned to this deferred call. - function push(bytes memory input, uint256 delay, SolverData[] memory data) + function push(CallObject[] memory callObjs, uint256 delay, SolverData[] memory data) public onlyLaminatorOrProxy returns (uint256 callSequenceNumber) { CallObjectHolder memory holder; - holder.callObjs = abi.decode(input, (CallObject[])); + holder.callObjs = callObjs; callSequenceNumber = _incrementSequenceNumber(); holder.initialized = true; holder.executed = false; diff --git a/src/lamination/Laminator.sol b/src/lamination/Laminator.sol index 1fe278a..f145445 100644 --- a/src/lamination/Laminator.sol +++ b/src/lamination/Laminator.sol @@ -55,41 +55,41 @@ contract Laminator is ILaminator { return address(uint160(uint256(hash))); } - /// @notice Gets the next sequence number of the LaminatedProxy associated with the sender. - /// @return sequenceNumber The sequence number of the next deferred function call. - function getNextSeqNumber() external view returns (uint256) { - address addr = computeProxyAddress(msg.sender); - uint32 size; - assembly { - size := extcodesize(addr) - } - if (size == 0) { - return 0; - } else { - return LaminatedProxy(payable(addr)).nextSequenceNumber(); - } - } - /// @notice Calls the `push` function into the LaminatedProxy associated with the sender. /// @dev Encodes the provided calldata and calls it into the `push` function of the proxy contract. /// A new proxy will be created if one does not already exist for the sender. - /// @param cData The calldata to be pushed. + /// @param callObjs The calldatas to be pushed. /// @param delay The delay for when the call can be executed. /// @param selector code identifier for solvers to select relevant actions /// @param dataValues to be used by solvers in serving the user objective /// @return sequenceNumber The sequence number of the deferred function call. - function pushToProxy(bytes calldata cData, uint32 delay, bytes32 selector, SolverData[] memory dataValues) + function pushToProxy(CallObject[] memory callObjs, uint32 delay, bytes32 selector, SolverData[] memory dataValues) external returns (uint256 sequenceNumber) { LaminatedProxy proxy = LaminatedProxy(payable(_getOrCreateProxy(msg.sender))); - sequenceNumber = proxy.push(cData, delay, dataValues); + sequenceNumber = proxy.push(callObjs, delay, dataValues); CallObject[] memory callObjs = abi.decode(cData, (CallObject[])); emit ProxyPushed(address(proxy), callObjs, sequenceNumber, selector, dataValues); } + /// @notice Gets the next sequence number of the LaminatedProxy associated with the sender. + /// @return sequenceNumber The sequence number of the next deferred function call. + function getNextSeqNumber() external view returns (uint256) { + address addr = computeProxyAddress(msg.sender); + uint32 size; + assembly { + size := extcodesize(addr) + } + if (size == 0) { + return 0; + } else { + return LaminatedProxy(payable(addr)).nextSequenceNumber(); + } + } + /// @notice Gets the proxy address for the sender or creates a new one if it doesn't exist. /// @dev Computes the proxy address for the sender using `computeProxyAddress`. If a proxy doesn't /// already exist, it will be created using the `create2` Ethereum opcode. From 38e583e5bb13283566e09612f3a3549e1d0e50d1 Mon Sep 17 00:00:00 2001 From: mevtxn Date: Mon, 25 Nov 2024 14:33:30 +0530 Subject: [PATCH 2/8] chore: update input byte args for lamination and callbreaker contracts --- src/interfaces/IFlashLoan.sol | 3 +- src/lamination/LaminatedProxy.sol | 4 +- src/lamination/Laminator.sol | 2 - src/timetravel/CallBreaker.sol | 87 ++++++++++++++----------------- 4 files changed, 42 insertions(+), 54 deletions(-) diff --git a/src/interfaces/IFlashLoan.sol b/src/interfaces/IFlashLoan.sol index 5457984..913f96b 100644 --- a/src/interfaces/IFlashLoan.sol +++ b/src/interfaces/IFlashLoan.sol @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.26; +import "../TimeTypes.sol"; interface IFlashLoan { - function flashLoan(address receiver, uint256 amountA, uint256 amountB, bytes calldata data) + function flashLoan(address receiver, uint256 amountA, uint256 amountB, CallObject[] calldata callObjs) external returns (bool); } diff --git a/src/lamination/LaminatedProxy.sol b/src/lamination/LaminatedProxy.sol index 8414836..9343439 100644 --- a/src/lamination/LaminatedProxy.sol +++ b/src/lamination/LaminatedProxy.sol @@ -159,7 +159,7 @@ contract LaminatedProxy is LaminatedStorage, ReentrancyGuard { /// @param callObjs The CallObjects containing information about the function call to execute. /// @return returnValue The return value from the executed function call. function execute(CallObject[] calldata callObjs) external onlyOwner nonReentrant returns (bytes memory) { - return _executeAll(callsToMake); + return _executeAll(callObjs); } /// @notice Copies the current job with a specified delay and condition. @@ -287,7 +287,7 @@ contract LaminatedProxy is LaminatedStorage, ReentrancyGuard { _checkInitialized(coh); CallObjectHolder memory holder = coh.load(); - return push(abi.encode(holder.callObjs), delay, holder.data); + return push(holder.callObjs, delay, holder.data); } /// @dev Safety checks before pushing calls to the LaminatedProxy diff --git a/src/lamination/Laminator.sol b/src/lamination/Laminator.sol index f145445..7b0ed78 100644 --- a/src/lamination/Laminator.sol +++ b/src/lamination/Laminator.sol @@ -68,10 +68,8 @@ contract Laminator is ILaminator { returns (uint256 sequenceNumber) { LaminatedProxy proxy = LaminatedProxy(payable(_getOrCreateProxy(msg.sender))); - sequenceNumber = proxy.push(callObjs, delay, dataValues); - CallObject[] memory callObjs = abi.decode(cData, (CallObject[])); emit ProxyPushed(address(proxy), callObjs, sequenceNumber, selector, dataValues); } diff --git a/src/timetravel/CallBreaker.sol b/src/timetravel/CallBreaker.sol index bcf96ab..6e21204 100644 --- a/src/timetravel/CallBreaker.sol +++ b/src/timetravel/CallBreaker.sol @@ -58,38 +58,34 @@ contract CallBreaker is CallBreakerStorage { /// @notice executes and verifies that the given calls, when executed, gives the correct return values /// @dev SECURITY NOTICE: This function is only callable when the portal is closed. It requires the caller to be an EOA. - /// @param callsBytes The bytes representing the calls to be verified - /// @param returnsBytes The bytes representing the returns to be verified against - /// @param associatedData Bytes representing associated data with the verify call, reserved for tipping the solver + /// @param callsBytes The calls to be executed + /// @param returnsBytes The returns to be compareed with return values from call obj execution + /// @param associatedData To be used in the execute and verify call, also reserved for tipping the solver function executeAndVerify( - bytes calldata callsBytes, - bytes calldata returnsBytes, - bytes calldata associatedData, - bytes calldata hintdices + CallObject[] calldata callsBytes, + ReturnObject[] calldata returnsBytes, + AdditionalData[] calldata associatedData ) external payable onlyPortalClosed { - CallObject[] memory calls = _setupExecutionData(callsBytes, returnsBytes, associatedData, hintdices); + CallObject[] memory calls = _setupExecutionData(callsBytes, returnsBytes, associatedData); _executeAndVerifyCalls(calls); } /// @notice fetches flash loan before executing and verifying call objects who might use the loaned amount /// @dev SECURITY NOTICE: This function is a temporary place holder for a nested call objects solution which is still under development /// TODO: Remove and replace with a generic version of nested call objects - /// @param callsBytes The bytes representing the calls to be verified - /// @param returnsBytes The bytes representing the returns to be verified against - /// @param associatedData Bytes representing associated data with the verify call, reserved for tipping the solver - /// @param hintdices Bytes representing indexes of the call objects - /// @param flashLoanData Bytes representing associated data with the verify call, reserved for tipping the solver + /// @param callObjs The calls to be executed + /// @param returnsBytes The returns to be compareed with return values from call obj execution + /// @param associatedData To be used in the execute and verify call, also reserved for tipping the solver + /// @param flashLoanData with information about aquiring the flash loan function executeAndVerify( - bytes calldata callsBytes, - bytes calldata returnsBytes, - bytes calldata associatedData, - bytes calldata hintdices, - bytes calldata flashLoanData + CallObject[] calldata callObjs, + ReturnObject[] calldata returnsBytes, + AdditionalData[] calldata associatedData, + FlashLoanData calldata flashLoanData ) external payable onlyPortalClosed { - _setupExecutionData(callsBytes, returnsBytes, associatedData, hintdices); - FlashLoanData memory _flashLoanData = abi.decode(flashLoanData, (FlashLoanData)); - IFlashLoan(_flashLoanData.provider).flashLoan( - address(this), _flashLoanData.amountA, _flashLoanData.amountB, callsBytes + _setupExecutionData(callObjs, returnsBytes, associatedData); + IFlashLoan(flashLoanData.provider).flashLoan( + address(this), flashLoanData.amountA, flashLoanData.amountB, callObjs ); } @@ -99,7 +95,7 @@ contract CallBreaker is CallBreakerStorage { * @param amountA The amount of tokens lent. * @param tokenB The second loan currency. * @param amountB The amount of tokens lent. - * @param data the execute and verify data + * @param calls The calls to be executed * @return true if the function executed successfully */ function onFlashLoan( @@ -108,10 +104,9 @@ contract CallBreaker is CallBreakerStorage { uint256 amountA, address tokenB, uint256 amountB, - bytes calldata data + CallObject[] calldata calls ) external onlyPortalOpen returns (bool) { emit CallBreakerFlashFunds(tokenA, amountA, tokenB, amountB); - CallObject[] memory calls = abi.decode(data, (CallObject[])); _executeAndVerifyCalls(calls); IERC20(tokenA).approve(msg.sender, amountA); @@ -121,21 +116,18 @@ contract CallBreaker is CallBreakerStorage { /// @notice Returns a value from the record of return values from the callObject. /// @dev This function also does some accounting to track the occurrence of a given pair of call and return values. - /// @param input The call to be executed, structured as a CallObjectWithIndex. + /// @param callObjWithIndex The call to be executed, structured as a CallObjectWithIndex. /// @return The return value from the record of return values. - function getReturnValue(bytes calldata input) external view returns (bytes memory) { - // Decode the input to obtain the CallObject and calculate a unique ID representing the call-return pair - CallObjectWithIndex memory callObjWithIndex = abi.decode(input, (CallObjectWithIndex)); + function getReturnValue(CallObjectWithIndex calldata callObjWithIndex) external view returns (bytes memory) { ReturnObject memory thisReturn = _getReturn(callObjWithIndex.index); return thisReturn.returnvalue; } /// @notice Gets a return value from the record of return values from the index number. /// @dev This function also does some accounting to track the occurrence of a given pair of call and return values. - /// @param index The call to be executed, structured as a CallObjectWithIndex. + /// @param index The index of call to be executed. /// @return The return value from the record of return values. function getReturnValue(uint256 index) external view returns (bytes memory) { - // Decode the input to obtain the CallObject and calculate a unique ID representing the call-return pair ReturnObject memory thisReturn = _getReturn(index); return thisReturn.returnvalue; } @@ -226,18 +218,14 @@ contract CallBreaker is CallBreakerStorage { } function _setupExecutionData( - bytes calldata callsBytes, - bytes calldata returnsBytes, - bytes calldata associatedData, - bytes calldata hintdices + CallObject[] calldata calls, + ReturnObject[] calldata returnValues, + AdditionalData[] calldata associatedData ) internal returns (CallObject[] memory) { if (msg.sender != tx.origin) { revert MustBeEOA(); } - CallObject[] memory calls = abi.decode(callsBytes, (CallObject[])); - ReturnObject[] memory returnValues = abi.decode(returnsBytes, (ReturnObject[])); - if (calls.length != returnValues.length) { revert LengthMismatch(); } @@ -245,6 +233,8 @@ contract CallBreaker is CallBreakerStorage { _setPortalOpen(calls, returnValues); _populateCallsAndReturnValues(calls, returnValues); _populateAssociatedDataStore(associatedData); + // TODO pass correct value of hintdices + bytes calldata hintdices; _populateHintdices(hintdices); _populateCallIndices(); @@ -302,10 +292,8 @@ contract CallBreaker is CallBreakerStorage { } /// @notice Populates the associatedDataStore with a list of key-value pairs - /// @param encodedData The abi-encoded list of (bytes32, bytes32) key-value pairs - function _populateAssociatedDataStore(bytes memory encodedData) internal { - AdditionalData[] memory associatedData = abi.decode(encodedData, (AdditionalData[])); - + /// @param associatedData The abi-encoded list of (bytes32, bytes32) key-value pairs + function _populateAssociatedDataStore(AdditionalData[] memory associatedData) internal { uint256 l = associatedData.length; for (uint256 i = 0; i < l; i++) { associatedDataKeyList.push(associatedData[i].key); @@ -314,13 +302,14 @@ contract CallBreaker is CallBreakerStorage { } function _populateHintdices(bytes memory encodedData) internal { - AdditionalData[] memory hintDices = abi.decode(encodedData, (AdditionalData[])); - - uint256 l = hintDices.length; - for (uint256 i = 0; i < l; i++) { - hintdicesStoreKeyList.push(hintDices[i].key); - hintdicesStore[hintDices[i].key].push(abi.decode(hintDices[i].value, (uint256))); // Note: the value being pushed can repeat itself if given wrong data - } + // TODO: merge with storing call objects + // AdditionalData[] memory hintDices = abi.decode(encodedData, (AdditionalData[])); + + // uint256 l = hintDices.length; + // for (uint256 i = 0; i < l; i++) { + // hintdicesStoreKeyList.push(hintDices[i].key); + // hintdicesStore[hintDices[i].key].push(abi.decode(hintDices[i].value, (uint256))); // Note: the value being pushed can repeat itself if given wrong data + // } } function _expectCallAt(CallObject memory callObj, uint256 index) internal view { From 0a7be2841c81b68205d2b705da7910ea79c9520f Mon Sep 17 00:00:00 2001 From: mevtxn Date: Mon, 25 Nov 2024 14:42:07 +0530 Subject: [PATCH 3/8] chore: update interface and CallBreaker contract for input args --- src/interfaces/ILaminator.sol | 4 ++-- src/timetravel/CallBreaker.sol | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/interfaces/ILaminator.sol b/src/interfaces/ILaminator.sol index 209aec1..8cf4eaa 100644 --- a/src/interfaces/ILaminator.sol +++ b/src/interfaces/ILaminator.sol @@ -7,12 +7,12 @@ interface ILaminator { /// @notice Calls the `push` function into the LaminatedProxy associated with the sender. /// @dev Encodes the provided calldata and calls it into the `push` function of the proxy contract. /// A new proxy will be created if one does not already exist for the sender. - /// @param cData The calldata to be pushed. + /// @param callObjs The calldatas to be pushed. /// @param delay The delay for when the call can be executed. /// @param selector code identifier for solvers to select relevant actions /// @param dataValues to be used by solvers in serving the user objective /// @return sequenceNumber The sequence number of the deferred function call. - function pushToProxy(bytes calldata cData, uint32 delay, bytes32 selector, SolverData[] memory dataValues) + function pushToProxy(CallObject[] memory callObjs, uint32 delay, bytes32 selector, SolverData[] memory dataValues) external returns (uint256 sequenceNumber); } diff --git a/src/timetravel/CallBreaker.sol b/src/timetravel/CallBreaker.sol index 6e21204..9c1b1e8 100644 --- a/src/timetravel/CallBreaker.sol +++ b/src/timetravel/CallBreaker.sol @@ -234,7 +234,7 @@ contract CallBreaker is CallBreakerStorage { _populateCallsAndReturnValues(calls, returnValues); _populateAssociatedDataStore(associatedData); // TODO pass correct value of hintdices - bytes calldata hintdices; + bytes memory hintdices; _populateHintdices(hintdices); _populateCallIndices(); From b0050db879ff89286a6123feded0645eb4dd2837 Mon Sep 17 00:00:00 2001 From: mevtxn Date: Mon, 25 Nov 2024 17:12:00 +0530 Subject: [PATCH 4/8] chore: fix solve-lib tests after input bytes arg changes --- test/solve-lib/CronCounterLib.sol | 4 ++-- test/solve-lib/DeFi/FlashLiquidityLib.sol | 4 ++-- test/solve-lib/DeFi/FlashLoanLib.sol | 11 +++++------ test/solve-lib/DeFi/SelfCheckoutLib.sol | 6 +++--- test/solve-lib/DeFi/SlippageProtectionLib.sol | 4 ++-- test/solve-lib/FlashPillLib.sol | 4 ++-- .../MEVTimeOracle/KITNDisburmentSchedulerLib.sol | 4 ++-- test/solve-lib/MEVTimeOracle/MEVTimeComputeLib.sol | 4 ++-- test/solve-lib/PnPLib.sol | 4 ++-- 9 files changed, 22 insertions(+), 23 deletions(-) diff --git a/test/solve-lib/CronCounterLib.sol b/test/solve-lib/CronCounterLib.sol index 4682425..0a31ac7 100644 --- a/test/solve-lib/CronCounterLib.sol +++ b/test/solve-lib/CronCounterLib.sol @@ -69,7 +69,7 @@ contract CronCounterLib { SolverData[] memory dataValues = Constants.emptyDataValues(); - return laminator.pushToProxy(abi.encode(pusherCallObjs), 1, "0x00", dataValues); + return laminator.pushToProxy(pusherCallObjs, 1, "0x00", dataValues); } function solverLand(uint256 laminatorSequenceNumber, address filler, bool isFirstTime) public { @@ -108,7 +108,7 @@ contract CronCounterLib { } callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); } } diff --git a/test/solve-lib/DeFi/FlashLiquidityLib.sol b/test/solve-lib/DeFi/FlashLiquidityLib.sol index 33ce4e2..3d7cb44 100644 --- a/test/solve-lib/DeFi/FlashLiquidityLib.sol +++ b/test/solve-lib/DeFi/FlashLiquidityLib.sol @@ -62,7 +62,7 @@ contract FlashLiquidityLib { SolverData[] memory dataValues = Constants.emptyDataValues(); - return laminator.pushToProxy(abi.encode(pusherCallObjs), 1, "0x00", dataValues); + return laminator.pushToProxy(pusherCallObjs, 1, "0x00", dataValues); } function solverLand( @@ -141,7 +141,7 @@ contract FlashLiquidityLib { hintdices[4] = AdditionalData({key: keccak256(abi.encode(callObjs[4])), value: abi.encode(4)}); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); } } diff --git a/test/solve-lib/DeFi/FlashLoanLib.sol b/test/solve-lib/DeFi/FlashLoanLib.sol index 7bdabe8..c19d62b 100644 --- a/test/solve-lib/DeFi/FlashLoanLib.sol +++ b/test/solve-lib/DeFi/FlashLoanLib.sol @@ -62,7 +62,7 @@ contract FlashLoanLib { SolverData[] memory dataValues = Constants.emptyDataValues(); - return laminator.pushToProxy(abi.encode(pusherCallObjs), 1, "0x00", dataValues); + return laminator.pushToProxy(pusherCallObjs, 1, "0x00", dataValues); } function solverLand( @@ -147,11 +147,10 @@ contract FlashLoanLib { hintdices[4] = AdditionalData({key: keccak256(abi.encode(callObjs[4])), value: abi.encode(4)}); callbreaker.executeAndVerify( - abi.encode(callObjs), - abi.encode(returnObjs), - abi.encode(associatedData), - abi.encode(hintdices), - abi.encode(generateFlashLoanData(address(flashLoan))) + callObjs, + returnObjs, + associatedData, + generateFlashLoanData(address(flashLoan)) ); } diff --git a/test/solve-lib/DeFi/SelfCheckoutLib.sol b/test/solve-lib/DeFi/SelfCheckoutLib.sol index 3761d89..b65d45b 100644 --- a/test/solve-lib/DeFi/SelfCheckoutLib.sol +++ b/test/solve-lib/DeFi/SelfCheckoutLib.sol @@ -61,9 +61,9 @@ contract SelfCheckoutLib { }); SolverData[] memory dataValues = Constants.emptyDataValues(); - laminator.pushToProxy(abi.encode(pusherCallObjs), 1, "0x00", dataValues); + laminator.pushToProxy(pusherCallObjs, 1, "0x00", dataValues); - return laminator.pushToProxy(abi.encode(pusherCallObjs), 1, "0x00", dataValues); + return laminator.pushToProxy(pusherCallObjs, 1, "0x00", dataValues); } // msg.sender here is the filler. all transfers of funds and approvals are made by the filler. @@ -125,7 +125,7 @@ contract SelfCheckoutLib { hintdices[2] = AdditionalData({key: keccak256(abi.encode(callObjs[2])), value: abi.encode(2)}); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); } } diff --git a/test/solve-lib/DeFi/SlippageProtectionLib.sol b/test/solve-lib/DeFi/SlippageProtectionLib.sol index 1927340..9598fc0 100644 --- a/test/solve-lib/DeFi/SlippageProtectionLib.sol +++ b/test/solve-lib/DeFi/SlippageProtectionLib.sol @@ -54,7 +54,7 @@ contract SlippageProtectionLib { pusherCallObjs[2] = CallObject({amount: _tipWei, addr: address(callbreaker), gas: 10000000, callvalue: ""}); SolverData[] memory dataValues = Constants.emptyDataValues(); - return laminator.pushToProxy(abi.encode(pusherCallObjs), 1, "0x00", dataValues); + return laminator.pushToProxy(pusherCallObjs, 1, "0x00", dataValues); } function solverLand(uint256 laminatorSequenceNumber, address filler, uint256 maxSlippage) public { @@ -96,7 +96,7 @@ contract SlippageProtectionLib { hintdices[1] = AdditionalData({key: keccak256(abi.encode(callObjs[1])), value: abi.encode(1)}); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); } } diff --git a/test/solve-lib/FlashPillLib.sol b/test/solve-lib/FlashPillLib.sol index 6376da9..6b6d13d 100644 --- a/test/solve-lib/FlashPillLib.sol +++ b/test/solve-lib/FlashPillLib.sol @@ -34,7 +34,7 @@ contract FlashPillLib { SolverData[] memory dataValues = Constants.emptyDataValues(); - return laminator.pushToProxy(abi.encode(pusherCallObjs), 1, "0x00", dataValues); + return laminator.pushToProxy(pusherCallObjs, 1, "0x00", dataValues); } function solverLand(uint256 laminatorSequenceNumber, address filler) public { @@ -64,7 +64,7 @@ contract FlashPillLib { hintdices[0] = AdditionalData({key: keccak256(abi.encode(callObjs[0])), value: abi.encode(0)}); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); } } diff --git a/test/solve-lib/MEVTimeOracle/KITNDisburmentSchedulerLib.sol b/test/solve-lib/MEVTimeOracle/KITNDisburmentSchedulerLib.sol index ae73ddd..e0b3441 100644 --- a/test/solve-lib/MEVTimeOracle/KITNDisburmentSchedulerLib.sol +++ b/test/solve-lib/MEVTimeOracle/KITNDisburmentSchedulerLib.sol @@ -70,7 +70,7 @@ contract KITNDisburmentSchedulerLib { SolverData[] memory dataValues = new SolverData[](1); dataValues[0] = data; - return laminator.pushToProxy(abi.encode(pusherCallObjs), 1, SELECTOR, dataValues); + return laminator.pushToProxy(pusherCallObjs, 1, SELECTOR, dataValues); } function solverLand(uint256 laminatorSequenceNumber, address filler) public { @@ -118,7 +118,7 @@ contract KITNDisburmentSchedulerLib { hintdices[1] = AdditionalData({key: keccak256(abi.encode(callObjs[1])), value: abi.encode(1)}); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); } diff --git a/test/solve-lib/MEVTimeOracle/MEVTimeComputeLib.sol b/test/solve-lib/MEVTimeOracle/MEVTimeComputeLib.sol index e969097..c6f2249 100644 --- a/test/solve-lib/MEVTimeOracle/MEVTimeComputeLib.sol +++ b/test/solve-lib/MEVTimeOracle/MEVTimeComputeLib.sol @@ -39,7 +39,7 @@ contract MEVTimeComputeLib { SolverData[] memory dataValues = Constants.emptyDataValues(); - return laminator.pushToProxy(abi.encode(pusherCallObjs), 1, "0x00", dataValues); + return laminator.pushToProxy(pusherCallObjs, 1, "0x00", dataValues); } function solverLand(uint256 laminatorSequenceNumber, address filler) public { @@ -83,7 +83,7 @@ contract MEVTimeComputeLib { hintdices[1] = AdditionalData({key: keccak256(abi.encode(callObjs[1])), value: abi.encode(1)}); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); } } diff --git a/test/solve-lib/PnPLib.sol b/test/solve-lib/PnPLib.sol index a753f60..2becbe6 100644 --- a/test/solve-lib/PnPLib.sol +++ b/test/solve-lib/PnPLib.sol @@ -48,7 +48,7 @@ contract PnPLib { pusherCallObjs[1] = CallObject({amount: _tipWei, addr: address(callbreaker), gas: 10000000, callvalue: ""}); SolverData[] memory dataValues = Constants.emptyDataValues(); - return laminator.pushToProxy(abi.encode(pusherCallObjs), 1, "0x00", dataValues); + return laminator.pushToProxy(pusherCallObjs, 1, "0x00", dataValues); } function solverLand(uint256 laminatorSequenceNumber, address filler) public { @@ -79,7 +79,7 @@ contract PnPLib { hintdices[0] = AdditionalData({key: keccak256(abi.encode(callObjs[0])), value: abi.encode(0)}); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); } } From 403606dce4d45b9729016a568299a6e250275e6b Mon Sep 17 00:00:00 2001 From: mevtxn Date: Mon, 25 Nov 2024 17:17:16 +0530 Subject: [PATCH 5/8] chore: fix tests --- test/CallBreaker.t.sol | 16 ++- test/Laminator.t.sol | 150 ++++++++++++-------------- test/NoopTurnerTest.t.sol | 2 +- test/SmarterContract.t.sol | 28 ++--- test/contracts/CallBreakerHarness.sol | 5 +- 5 files changed, 90 insertions(+), 111 deletions(-) diff --git a/test/CallBreaker.t.sol b/test/CallBreaker.t.sol index 00edca6..e52de0c 100644 --- a/test/CallBreaker.t.sol +++ b/test/CallBreaker.t.sol @@ -144,9 +144,8 @@ contract CallBreakerTest is Test { value: abi.encodePacked(address(0xdeadbeef)) }); associatedData[1] = AdditionalData({key: keccak256(abi.encodePacked("pullIndex")), value: abi.encode(0)}); - bytes memory encodedData = abi.encode(associatedData); - callbreaker.populateAssociatedDataStoreHarness(encodedData); + callbreaker.populateAssociatedDataStoreHarness(associatedData); } function testPopulateHintdices() external { @@ -170,9 +169,8 @@ contract CallBreakerTest is Test { value: abi.encodePacked(address(0xdeadbeef)) }); associatedData[1] = AdditionalData({key: keccak256(abi.encodePacked("pullIndex")), value: abi.encode(0)}); - bytes memory encodedData = abi.encode(associatedData); - callbreaker.populateAssociatedDataStoreHarness(encodedData); + callbreaker.populateAssociatedDataStoreHarness(associatedData); AdditionalData[] memory hintdices = new AdditionalData[](2); hintdices[0] = AdditionalData({key: keccak256(abi.encode(calls[0])), value: abi.encode(0)}); @@ -203,9 +201,8 @@ contract CallBreakerTest is Test { value: abi.encodePacked(address(0xdeadbeef)) }); associatedData[1] = AdditionalData({key: keccak256(abi.encodePacked("pullIndex")), value: abi.encode(0)}); - bytes memory encodedData = abi.encode(associatedData); - callbreaker.populateAssociatedDataStoreHarness(encodedData); + callbreaker.populateAssociatedDataStoreHarness(associatedData); AdditionalData[] memory hintdices = new AdditionalData[](2); hintdices[0] = AdditionalData({key: keccak256(abi.encode(calls[0])), value: abi.encode(0)}); @@ -237,9 +234,8 @@ contract CallBreakerTest is Test { value: abi.encodePacked(address(0xdeadbeef)) }); associatedData[1] = AdditionalData({key: keccak256(abi.encodePacked("pullIndex")), value: abi.encode(0)}); - bytes memory encodedData = abi.encode(associatedData); - callbreaker.populateAssociatedDataStoreHarness(encodedData); + callbreaker.populateAssociatedDataStoreHarness(associatedData); AdditionalData[] memory hintdices = new AdditionalData[](2); hintdices[0] = AdditionalData({key: keccak256(abi.encode(calls[0])), value: abi.encode(0)}); @@ -286,10 +282,10 @@ contract CallBreakerTest is Test { returnValues[1] = ReturnObject({returnvalue: "bar"}); callbreaker.resetTraceStoresWithHarness(calls, returnValues); - bytes memory input0 = abi.encode(CallObjectWithIndex({index: 0, callObj: calls[0]})); + CallObjectWithIndex memory input0 = CallObjectWithIndex({index: 0, callObj: calls[0]}); bytes memory output0 = callbreaker.getReturnValue(input0); - bytes memory input1 = abi.encode(CallObjectWithIndex({index: 1, callObj: calls[1]})); + CallObjectWithIndex memory input1 = CallObjectWithIndex({index: 1, callObj: calls[1]}); bytes memory output1 = callbreaker.getReturnValue(input1); assertEq(keccak256(returnValues[0].returnvalue), keccak256(output0)); diff --git a/test/Laminator.t.sol b/test/Laminator.t.sol index 03db1e2..061b108 100644 --- a/test/Laminator.t.sol +++ b/test/Laminator.t.sol @@ -77,14 +77,13 @@ contract LaminatorTest is Test { gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val1) }); - bytes memory cData = abi.encode(callObj1); SolverData[] memory dataValues = Constants.emptyDataValues(); vm.expectEmit(true, true, true, true); emit ProxyPushed(address(proxy), callObj1, 0, DEFAULT_CODE, dataValues); emit CallPushed(callObj1, 0, dataValues); - uint256 sequenceNumber1 = laminator.pushToProxy(cData, 1, DEFAULT_CODE, dataValues); + uint256 sequenceNumber1 = laminator.pushToProxy(callObj1, 1, DEFAULT_CODE, dataValues); assertEq(sequenceNumber1, 0); nextSeq = laminator.getNextSeqNumber(); @@ -99,11 +98,10 @@ contract LaminatorTest is Test { gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val2) }); - cData = abi.encode(callObj2); vm.expectEmit(true, true, true, true); emit ProxyPushed(address(proxy), callObj2, 1, DEFAULT_CODE, dataValues); emit CallPushed(callObj1, 0, dataValues); - uint256 sequenceNumber2 = laminator.pushToProxy(cData, 1, DEFAULT_CODE, dataValues); + uint256 sequenceNumber2 = laminator.pushToProxy(callObj2, 1, DEFAULT_CODE, dataValues); assertEq(sequenceNumber2, 1); nextSeq = laminator.getNextSeqNumber(); @@ -126,18 +124,17 @@ contract LaminatorTest is Test { } function testPushToProxyDataValues() public { - CallObject[] memory callObj = new CallObject[](1); - callObj[0] = CallObject({ + CallObject[] memory callObjs = new CallObject[](1); + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", 1) }); - bytes memory cData = abi.encode(callObj); SolverData[] memory dataValues = new SolverData[](1); dataValues[0] = SolverData({name: "MockVariable", datatype: DATATYPE.UINT256, value: "1"}); - uint256 sequenceNumber = laminator.pushToProxy(cData, 0, DEFAULT_CODE, dataValues); + uint256 sequenceNumber = laminator.pushToProxy(callObjs, 0, DEFAULT_CODE, dataValues); CallObjectHolder memory holder = proxy.deferredCalls(sequenceNumber); assertEq(holder.data.length, 1); assertEq(abi.encode(dataValues[0]), abi.encode(holder.data[0])); @@ -147,23 +144,22 @@ contract LaminatorTest is Test { function testDelayedPushToProxy0delayWorks() public { // push sequence number 0. it should emit 42. uint256 val = 42; - CallObject[] memory callObj = new CallObject[](1); - callObj[0] = CallObject({ + CallObject[] memory callObjs = new CallObject[](1); + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - bytes memory cData = abi.encode(callObj); SolverData[] memory dataValues = Constants.emptyDataValues(); - uint256 sequenceNumber = laminator.pushToProxy(cData, 0, DEFAULT_CODE, dataValues); + uint256 sequenceNumber = laminator.pushToProxy(callObjs, 0, DEFAULT_CODE, dataValues); assertEq(sequenceNumber, 0); vm.prank(address(callBreaker), address(callBreaker)); // try pulls as a random address, make sure the events were emitted vm.expectEmit(true, true, true, true); - emit CallPulled(callObj, 0); + emit CallPulled(callObjs, 0); proxy.pull(0); } @@ -171,16 +167,16 @@ contract LaminatorTest is Test { function testDelayedPushToProxy1delayNoRollFails() public { // push sequence number 0. it should emit 42. uint256 val = 42; - CallObject memory callObj = CallObject({ + CallObject[] memory callObjs = new CallObject[](1); + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - bytes memory cData = abi.encode(callObj); SolverData[] memory dataValues = Constants.emptyDataValues(); - uint256 sequenceNumber = laminator.pushToProxy(cData, 1, DEFAULT_CODE, dataValues); + uint256 sequenceNumber = laminator.pushToProxy(callObjs, 1, DEFAULT_CODE, dataValues); assertEq(sequenceNumber, 0); // try pulls, make sure it reverts @@ -193,16 +189,16 @@ contract LaminatorTest is Test { function testDelayedPushToProxy3delay1rollFails() public { // push sequence number 0. it should emit 42. uint256 val = 42; - CallObject memory callObj = CallObject({ + CallObject[] memory callObjs; + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - bytes memory cData = abi.encode(callObj); SolverData[] memory dataValues = Constants.emptyDataValues(); - uint256 sequenceNumber = laminator.pushToProxy(cData, 3, DEFAULT_CODE, dataValues); + uint256 sequenceNumber = laminator.pushToProxy(callObjs, 3, DEFAULT_CODE, dataValues); assertEq(sequenceNumber, 0); vm.roll(block.number + 1); @@ -218,18 +214,18 @@ contract LaminatorTest is Test { laminator.harness_getOrCreateProxy(address(this)); uint256 val = 42; - CallObject memory callObj = CallObject({ + CallObject[] memory callObjs; + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - bytes memory cData = abi.encode(callObj); SolverData[] memory dataValues = Constants.emptyDataValues(); vm.prank(randomFriendAddress, randomFriendAddress); vm.expectRevert(LaminatedProxy.NotLaminatorOrProxy.selector); - proxy.push(cData, 0, dataValues); + proxy.push(callObjs, 0, dataValues); } // ensure pushes as the laminator work @@ -237,20 +233,19 @@ contract LaminatorTest is Test { laminator.harness_getOrCreateProxy(address(this)); uint256 val = 42; - CallObject[] memory callObj = new CallObject[](1); - callObj[0] = CallObject({ + CallObject[] memory callObjs = new CallObject[](1); + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - bytes memory cData = abi.encode(callObj); SolverData[] memory dataValues = Constants.emptyDataValues(); vm.prank(address(laminator), address(laminator)); vm.expectEmit(true, true, true, true); - emit CallPushed(callObj, 0, dataValues); - proxy.push(cData, 1, dataValues); + emit CallPushed(callObjs, 0, dataValues); + proxy.push(callObjs, 1, dataValues); } function testExecute() public { @@ -264,44 +259,41 @@ contract LaminatorTest is Test { gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - bytes memory cData = abi.encode(callObj); vm.expectEmit(true, true, true, true); emit CallExecuted(callObj[0]); - proxy.execute(cData); + proxy.execute(callObj); } function testExecuteRevertNotOwner() public { laminator.harness_getOrCreateProxy(address(this)); uint256 val = 42; - CallObject[] memory callObj = new CallObject[](1); - callObj[0] = CallObject({ + CallObject[] memory callObjs = new CallObject[](1); + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - bytes memory cData = abi.encode(callObj); vm.prank(address(laminator), address(laminator)); vm.expectRevert(LaminatedProxy.NotOwner.selector); - proxy.execute(cData); + proxy.execute(callObjs); } // test cancel pending call function testCancelPending() public { // push once uint256 val = 42; - CallObject[] memory callObj = new CallObject[](1); - callObj[0] = CallObject({ + CallObject[] memory callObjs = new CallObject[](1); + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - bytes memory cData = abi.encode(callObj); SolverData[] memory dataValues = Constants.emptyDataValues(); - uint256 sequenceNumber = laminator.pushToProxy(cData, 0, DEFAULT_CODE, dataValues); + uint256 sequenceNumber = laminator.pushToProxy(callObjs, 0, DEFAULT_CODE, dataValues); assertEq(sequenceNumber, 0); // pull once @@ -321,10 +313,9 @@ contract LaminatorTest is Test { gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - bytes memory cData = abi.encode(callObj1); SolverData[] memory dataValues = Constants.emptyDataValues(); - laminator.pushToProxy(cData, 0, DEFAULT_CODE, dataValues); + laminator.pushToProxy(callObj1, 0, DEFAULT_CODE, dataValues); CallObject[] memory callObj2 = new CallObject[](1); callObj2[0] = CallObject({ @@ -333,8 +324,7 @@ contract LaminatorTest is Test { gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - cData = abi.encode(callObj2); - laminator.pushToProxy(cData, 0, DEFAULT_CODE, dataValues); + laminator.pushToProxy(callObj2, 0, DEFAULT_CODE, dataValues); proxy.cancelAllPending(); @@ -351,17 +341,16 @@ contract LaminatorTest is Test { function testPullFromProxyAsRandomAddress() public { // push once uint256 val = 42; - CallObject[] memory callObj = new CallObject[](1); - callObj[0] = CallObject({ + CallObject[] memory callObjs = new CallObject[](1); + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - bytes memory cData = abi.encode(callObj); SolverData[] memory dataValues = Constants.emptyDataValues(); - uint256 sequenceNumber = laminator.pushToProxy(cData, 0, DEFAULT_CODE, dataValues); + uint256 sequenceNumber = laminator.pushToProxy(callObjs, 0, DEFAULT_CODE, dataValues); assertEq(sequenceNumber, 0); // pull once @@ -374,17 +363,16 @@ contract LaminatorTest is Test { function testDoublePull() public { // push once uint256 val = 42; - CallObject[] memory callObj = new CallObject[](1); - callObj[0] = CallObject({ + CallObject[] memory callObjs = new CallObject[](1); + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - bytes memory cData = abi.encode(callObj); SolverData[] memory dataValues = Constants.emptyDataValues(); - uint256 sequenceNumber = laminator.pushToProxy(cData, 0, DEFAULT_CODE, dataValues); + uint256 sequenceNumber = laminator.pushToProxy(callObjs, 0, DEFAULT_CODE, dataValues); assertEq(sequenceNumber, 0); // pull once @@ -400,23 +388,22 @@ contract LaminatorTest is Test { function testUninitializedPull() public { // push once uint256 val = 42; - CallObject[] memory callObj = new CallObject[](2); - callObj[0] = CallObject({ + CallObject[] memory callObjs = new CallObject[](2); + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - callObj[1] = CallObject({ + callObjs[1] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - bytes memory cData = abi.encode(callObj); SolverData[] memory dataValues = Constants.emptyDataValues(); - uint256 sequenceNumber = laminator.pushToProxy(cData, 0, DEFAULT_CODE, dataValues); + uint256 sequenceNumber = laminator.pushToProxy(callObjs, 0, DEFAULT_CODE, dataValues); assertEq(sequenceNumber, 0); // try to pull out of order @@ -429,17 +416,16 @@ contract LaminatorTest is Test { function testRevertCall() public { laminator.harness_getOrCreateProxy(address(this)); - CallObject[] memory callObj = new CallObject[](1); - callObj[0] = CallObject({ + CallObject[] memory callObjs = new CallObject[](1); + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("reverter()") }); - bytes memory cData = abi.encode(callObj); SolverData[] memory dataValues = Constants.emptyDataValues(); - uint256 sequenceNumber = laminator.pushToProxy(cData, 1, DEFAULT_CODE, dataValues); + uint256 sequenceNumber = laminator.pushToProxy(callObjs, 1, DEFAULT_CODE, dataValues); assertEq(sequenceNumber, 0); vm.roll(block.number + 1); @@ -452,18 +438,18 @@ contract LaminatorTest is Test { // ensure executions called directly to proxy as a random address don't work function testExecuteAsRandomAddress() public { laminator.harness_getOrCreateProxy(address(this)); - CallObject memory callObj = CallObject({ + CallObject[] memory callObjs; + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", 42) }); - bytes memory cData = abi.encode(callObj); // pretend to be a random address and call directly, should fail vm.prank(randomFriendAddress); vm.expectRevert(LaminatedProxy.NotOwner.selector); - proxy.execute(cData); + proxy.execute(callObjs); } // ensure executions called into proxy directly as the laminator do work @@ -476,26 +462,25 @@ contract LaminatorTest is Test { gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", 42) }); - bytes memory cData = abi.encode(callObjs); // pretend to be the laminator and call directly, should work vm.prank(address(laminator)); vm.expectRevert(LaminatedProxy.NotOwner.selector); - proxy.execute(cData); + proxy.execute(callObjs); } // ensure executions as the owner directly into the proxy contract do NOT work function testExecuteAsOwner() public { laminator.harness_getOrCreateProxy(address(this)); - CallObject memory callObj = CallObject({ + CallObject[] memory callObjs; + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", 42) }); - bytes memory cData = abi.encode(callObj); - proxy.execute(cData); + proxy.execute(callObjs); } /// cleanupStorage tests @@ -520,74 +505,72 @@ contract LaminatorTest is Test { // ensure executions as random address through the laminator do not work function testExecuteAsRandomAddressFromLaminator() public { laminator.harness_getOrCreateProxy(address(this)); - CallObject memory callObj = CallObject({ + CallObject[] memory callObjs; + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", 42) }); - bytes memory cData = abi.encode(callObj); // pretend to be a random address and call directly, should fail vm.prank(randomFriendAddress); vm.expectRevert(LaminatedProxy.NotOwner.selector); - proxy.execute(cData); + proxy.execute(callObjs); } // ensure executions as laminator through the laminator do work function testExecuteAsLaminatorAddressFromLaminator() public { laminator.harness_getOrCreateProxy(address(this)); - CallObject memory callObj = CallObject({ + CallObject[] memory callObjs; + callObjs[0] = CallObject({ amount: 0, addr: address(dummy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", 42) }); - bytes memory cData = abi.encode(callObj); - proxy.execute(cData); + proxy.execute(callObjs); } function testGetExecutingCallObject() public { laminator.harness_getOrCreateProxy(address(this)); - CallObject[] memory callObj = new CallObject[](1); - callObj[0] = CallObject({ + CallObject[] memory callObjs = new CallObject[](1); + callObjs[0] = CallObject({ amount: 0, addr: address(proxy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("getExecutingCallObject()") }); - bytes memory cData = abi.encode(callObj); SolverData[] memory dataValues = Constants.emptyDataValues(); - laminator.pushToProxy(cData, 0, DEFAULT_CODE, dataValues); + laminator.pushToProxy(callObjs, 0, DEFAULT_CODE, dataValues); vm.prank(address(callBreaker), address(callBreaker)); bytes memory returnValue = proxy.pull(0); ReturnObject[] memory returnObj = abi.decode(returnValue, (ReturnObject[])); CallObject memory returnCallObject = abi.decode(returnObj[0].returnvalue, (CallObject)); - assertEq(abi.encode(returnCallObject), abi.encode(callObj[0])); + assertEq(abi.encode(returnCallObject), abi.encode(callObjs[0])); } function testGetExecutingCallObjectHolder() public { laminator.harness_getOrCreateProxy(address(this)); - CallObject[] memory callObj = new CallObject[](1); - callObj[0] = CallObject({ + CallObject[] memory callObjs = new CallObject[](1); + callObjs[0] = CallObject({ amount: 0, addr: address(proxy), gas: saneGasLeft(), callvalue: abi.encodeWithSignature("getExecutingCallObjectHolder()") }); - bytes memory cData = abi.encode(callObj); SolverData[] memory dataValues = Constants.emptyDataValues(); - laminator.pushToProxy(cData, 0, DEFAULT_CODE, dataValues); + laminator.pushToProxy(callObjs, 0, DEFAULT_CODE, dataValues); vm.prank(address(callBreaker), address(callBreaker)); bytes memory returnValue = proxy.pull(0); ReturnObject[] memory returnObj = abi.decode(returnValue, (ReturnObject[])); CallObjectHolder memory returnCallObjectHolder = abi.decode(returnObj[0].returnvalue, (CallObjectHolder)); - assertEq(abi.encode(returnCallObjectHolder.callObjs[0]), abi.encode(callObj[0])); + assertEq(abi.encode(returnCallObjectHolder.callObjs[0]), abi.encode(callObjs[0])); } function testCleanupLaminatorStorage() public { @@ -601,11 +584,10 @@ contract LaminatorTest is Test { gas: saneGasLeft(), callvalue: abi.encodeWithSignature("emitArg(uint256)", val) }); - bytes memory cData = abi.encode(callObj1); uint256[] memory sequenceNumber = new uint256[](1); SolverData[] memory dataValues = Constants.emptyDataValues(); - sequenceNumber[0] = laminator.pushToProxy(cData, 0, DEFAULT_CODE, dataValues); + sequenceNumber[0] = laminator.pushToProxy(callObj1, 0, DEFAULT_CODE, dataValues); // clean before any pull changess nothing proxy.cleanupLaminatorStorage(sequenceNumber); diff --git a/test/NoopTurnerTest.t.sol b/test/NoopTurnerTest.t.sol index 6e59e9c..a4493e5 100644 --- a/test/NoopTurnerTest.t.sol +++ b/test/NoopTurnerTest.t.sol @@ -41,7 +41,7 @@ contract NoopTurnerTest is Test { vm.prank(address(0xdeadbeef), address(0xdeadbeef)); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); } } diff --git a/test/SmarterContract.t.sol b/test/SmarterContract.t.sol index 1ef9c4a..c7bf86a 100644 --- a/test/SmarterContract.t.sol +++ b/test/SmarterContract.t.sol @@ -116,7 +116,7 @@ contract SmarterContractTest is Test { SolverData[] memory dataValues = Constants.emptyDataValues(); vm.prank(pusher, pusher); - laminator.pushToProxy(abi.encode(pusherCallObjs), 0, DEFAULT_CODE, dataValues); + laminator.pushToProxy(pusherCallObjs, 0, DEFAULT_CODE, dataValues); CallObject[] memory callObjs = new CallObject[](2); ReturnObject[] memory returnObjs = new ReturnObject[](2); @@ -144,7 +144,7 @@ contract SmarterContractTest is Test { vm.prank(address(0xdeadbeef), address(0xdeadbeef)); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); } @@ -164,7 +164,7 @@ contract SmarterContractTest is Test { SolverData[] memory dataValues = Constants.emptyDataValues(); vm.prank(pusher, pusher); - laminator.pushToProxy(abi.encode(pusherCallObjs), 0, DEFAULT_CODE, dataValues); + laminator.pushToProxy(pusherCallObjs, 0, DEFAULT_CODE, dataValues); CallObject[] memory callObjs = new CallObject[](2); ReturnObject[] memory returnObjs = new ReturnObject[](2); @@ -193,7 +193,7 @@ contract SmarterContractTest is Test { vm.prank(address(0xdeadbeef), address(0xdeadbeef)); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); } @@ -213,7 +213,7 @@ contract SmarterContractTest is Test { SolverData[] memory dataValues = Constants.emptyDataValues(); vm.prank(pusher, pusher); - laminator.pushToProxy(abi.encode(pusherCallObjs), 0, DEFAULT_CODE, dataValues); + laminator.pushToProxy(pusherCallObjs, 0, DEFAULT_CODE, dataValues); CallObject[] memory callObjs = new CallObject[](2); ReturnObject[] memory returnObjs = new ReturnObject[](2); @@ -242,7 +242,7 @@ contract SmarterContractTest is Test { vm.prank(address(0xdeadbeef), address(0xdeadbeef)); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); } @@ -262,7 +262,7 @@ contract SmarterContractTest is Test { SolverData[] memory dataValues = Constants.emptyDataValues(); vm.prank(pusher, pusher); - laminator.pushToProxy(abi.encode(pusherCallObjs), 0, DEFAULT_CODE, dataValues); + laminator.pushToProxy(pusherCallObjs, 0, DEFAULT_CODE, dataValues); CallObject[] memory callObjs = new CallObject[](2); ReturnObject[] memory returnObjs = new ReturnObject[](2); @@ -291,7 +291,7 @@ contract SmarterContractTest is Test { vm.prank(address(0xdeadbeef), address(0xdeadbeef)); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); } @@ -311,7 +311,7 @@ contract SmarterContractTest is Test { SolverData[] memory dataValues = Constants.emptyDataValues(); vm.prank(pusher, pusher); - laminator.pushToProxy(abi.encode(pusherCallObjs), 0, DEFAULT_CODE, dataValues); + laminator.pushToProxy(pusherCallObjs, 0, DEFAULT_CODE, dataValues); CallObject[] memory callObjs = new CallObject[](2); ReturnObject[] memory returnObjs = new ReturnObject[](2); @@ -345,7 +345,7 @@ contract SmarterContractTest is Test { vm.prank(address(0xdeadbeef), address(0xdeadbeef)); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); callbreakerHarness.setPortalOpen(callObjs, returnObjs); @@ -371,7 +371,7 @@ contract SmarterContractTest is Test { SolverData[] memory dataValues = Constants.emptyDataValues(); vm.prank(pusher, pusher); - laminator.pushToProxy(abi.encode(pusherCallObjs), 0, DEFAULT_CODE, dataValues); + laminator.pushToProxy(pusherCallObjs, 0, DEFAULT_CODE, dataValues); CallObject[] memory callObjs = new CallObject[](2); ReturnObject[] memory returnObjs = new ReturnObject[](2); @@ -405,7 +405,7 @@ contract SmarterContractTest is Test { vm.prank(address(0xdeadbeef), address(0xdeadbeef)); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); uint256 callLength = 3; @@ -444,7 +444,7 @@ contract SmarterContractTest is Test { SolverData[] memory dataValues = Constants.emptyDataValues(); vm.prank(pusher, pusher); - laminator.pushToProxy(abi.encode(pusherCallObjs), 0, DEFAULT_CODE, dataValues); + laminator.pushToProxy(pusherCallObjs, 0, DEFAULT_CODE, dataValues); CallObject[] memory callObjs = new CallObject[](2); ReturnObject[] memory returnObjs = new ReturnObject[](2); @@ -478,7 +478,7 @@ contract SmarterContractTest is Test { vm.prank(address(0xdeadbeef), address(0xdeadbeef)); callbreaker.executeAndVerify( - abi.encode(callObjs), abi.encode(returnObjs), abi.encode(associatedData), abi.encode(hintdices) + callObjs, returnObjs, associatedData ); uint256 callLength = 3; diff --git a/test/contracts/CallBreakerHarness.sol b/test/contracts/CallBreakerHarness.sol index 8e568bf..281dd94 100644 --- a/test/contracts/CallBreakerHarness.sol +++ b/test/contracts/CallBreakerHarness.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.26; import {CallBreaker, CallObject, ReturnObject} from "src/timetravel/CallBreaker.sol"; +import "src/CallBreakerTypes.sol"; contract CallBreakerHarness is CallBreaker { function setPortalOpen(CallObject[] memory calls, ReturnObject[] memory returnValues) public { @@ -27,8 +28,8 @@ contract CallBreakerHarness is CallBreaker { _cleanUpStorage(); } - function populateAssociatedDataStoreHarness(bytes memory encodedData) public { - _populateAssociatedDataStore(encodedData); + function populateAssociatedDataStoreHarness(AdditionalData[] memory associatedData) public { + _populateAssociatedDataStore(associatedData); } function populateHintdicesHarness(bytes memory encodedData) public { From 7088f1564c341e5300adcfa337f991ea3667b77f Mon Sep 17 00:00:00 2001 From: mevtxn Date: Tue, 26 Nov 2024 18:31:50 +0530 Subject: [PATCH 6/8] fix: store hintdices in _populateCallsAndReturnValues function --- src/timetravel/CallBreaker.sol | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/timetravel/CallBreaker.sol b/src/timetravel/CallBreaker.sol index 9c1b1e8..3482f13 100644 --- a/src/timetravel/CallBreaker.sol +++ b/src/timetravel/CallBreaker.sol @@ -233,9 +233,6 @@ contract CallBreaker is CallBreakerStorage { _setPortalOpen(calls, returnValues); _populateCallsAndReturnValues(calls, returnValues); _populateAssociatedDataStore(associatedData); - // TODO pass correct value of hintdices - bytes memory hintdices; - _populateHintdices(hintdices); _populateCallIndices(); return calls; @@ -279,6 +276,10 @@ contract CallBreaker is CallBreakerStorage { for (uint256 i = 0; i < calls.length; i++) { callStore.push().store(calls[i]); returnStore.push(returnValues[i]); + + bytes32 key = keccak256(abi.encode(calls[i])); + hintdicesStoreKeyList.push(key); + hintdicesStore[key].push(i); } } @@ -301,17 +302,6 @@ contract CallBreaker is CallBreakerStorage { } } - function _populateHintdices(bytes memory encodedData) internal { - // TODO: merge with storing call objects - // AdditionalData[] memory hintDices = abi.decode(encodedData, (AdditionalData[])); - - // uint256 l = hintDices.length; - // for (uint256 i = 0; i < l; i++) { - // hintdicesStoreKeyList.push(hintDices[i].key); - // hintdicesStore[hintDices[i].key].push(abi.decode(hintDices[i].value, (uint256))); // Note: the value being pushed can repeat itself if given wrong data - // } - } - function _expectCallAt(CallObject memory callObj, uint256 index) internal view { if (keccak256(abi.encode(_getCall(index))) != keccak256(abi.encode(callObj))) { revert CallPositionFailed(callObj, index); From f19d7cbcc6bb995c337ae071eb03f44f80220b70 Mon Sep 17 00:00:00 2001 From: mevtxn Date: Tue, 26 Nov 2024 19:33:09 +0530 Subject: [PATCH 7/8] chore: fix tests --- test/CallBreaker.t.sol | 54 +-------------------------- test/Laminator.t.sol | 12 +++--- test/contracts/CallBreakerHarness.sol | 4 -- test/examples/DeFi/MockFlashLoan.sol | 7 ++-- test/solve-lib/DeFi/FlashLoanLib.sol | 10 +---- 5 files changed, 12 insertions(+), 75 deletions(-) diff --git a/test/CallBreaker.t.sol b/test/CallBreaker.t.sol index e52de0c..c314cdd 100644 --- a/test/CallBreaker.t.sol +++ b/test/CallBreaker.t.sol @@ -109,7 +109,7 @@ contract CallBreakerTest is Test { assertEq(callbreaker.getReturnStoreLengthHarness(), 2); assertEq(callbreaker.getCallListLengthHarness(), 2); assertEq(callbreaker.getAssociatedDataKeyListLengthHarness(), 0); - assertEq(callbreaker.getHintdicesStoreKeyListLengthHarness(), 0); + assertEq(callbreaker.getHintdicesStoreKeyListLengthHarness(), 2); callbreaker._executeAndVerifyCallHarness(0); callbreaker._executeAndVerifyCallHarness(1); @@ -148,38 +148,6 @@ contract CallBreakerTest is Test { callbreaker.populateAssociatedDataStoreHarness(associatedData); } - function testPopulateHintdices() external { - CallObject[] memory calls = new CallObject[](2); - calls[0] = CallObject({amount: 0, addr: address(0xdeadbeef), gas: 1000000, callvalue: ""}); - calls[1] = CallObject({amount: 0, addr: address(0xdeadbeef), gas: 1000000, callvalue: ""}); - - ReturnObject[] memory returnValues = new ReturnObject[](2); - returnValues[0] = ReturnObject({returnvalue: ""}); - returnValues[1] = ReturnObject({returnvalue: ""}); - - callbreaker.resetTraceStoresWithHarness(calls, returnValues); - callbreaker.populateCallIndicesHarness(); - - callbreaker._executeAndVerifyCallHarness(0); - callbreaker._executeAndVerifyCallHarness(1); - - AdditionalData[] memory associatedData = new AdditionalData[](2); - associatedData[0] = AdditionalData({ - key: keccak256(abi.encodePacked("tipYourBartender")), - value: abi.encodePacked(address(0xdeadbeef)) - }); - associatedData[1] = AdditionalData({key: keccak256(abi.encodePacked("pullIndex")), value: abi.encode(0)}); - - callbreaker.populateAssociatedDataStoreHarness(associatedData); - - AdditionalData[] memory hintdices = new AdditionalData[](2); - hintdices[0] = AdditionalData({key: keccak256(abi.encode(calls[0])), value: abi.encode(0)}); - hintdices[1] = AdditionalData({key: keccak256(abi.encode(calls[1])), value: abi.encode(1)}); - bytes memory hintindices = abi.encode(hintdices); - - callbreaker.populateHintdicesHarness(hintindices); - } - function testInsertIntoHintdices() external { CallObject[] memory calls = new CallObject[](2); calls[0] = CallObject({amount: 0, addr: address(0xdeadbeef), gas: 1000000, callvalue: ""}); @@ -204,12 +172,6 @@ contract CallBreakerTest is Test { callbreaker.populateAssociatedDataStoreHarness(associatedData); - AdditionalData[] memory hintdices = new AdditionalData[](2); - hintdices[0] = AdditionalData({key: keccak256(abi.encode(calls[0])), value: abi.encode(0)}); - hintdices[1] = AdditionalData({key: keccak256(abi.encode(calls[1])), value: abi.encode(1)}); - bytes memory hintindices = abi.encode(hintdices); - - callbreaker.populateHintdicesHarness(hintindices); callbreaker.insertIntoHintdicesHarness(keccak256(abi.encode(calls[0])), 2); } @@ -237,13 +199,6 @@ contract CallBreakerTest is Test { callbreaker.populateAssociatedDataStoreHarness(associatedData); - AdditionalData[] memory hintdices = new AdditionalData[](2); - hintdices[0] = AdditionalData({key: keccak256(abi.encode(calls[0])), value: abi.encode(0)}); - hintdices[1] = AdditionalData({key: keccak256(abi.encode(calls[1])), value: abi.encode(1)}); - bytes memory hintindices = abi.encode(hintdices); - - callbreaker.populateHintdicesHarness(hintindices); - callbreaker.insertIntoHintdicesHarness(keccak256(abi.encode(calls[0])), 2); callbreaker.insertIntoAssociatedDataStore(keccak256(abi.encodePacked("x")), abi.encode(uint256(0))); @@ -259,13 +214,6 @@ contract CallBreakerTest is Test { callbreaker.resetTraceStoresWithHarness(calls, returnValues); callbreaker.populateCallIndicesHarness(); - AdditionalData[] memory hintdices = new AdditionalData[](2); - - hintdices[0] = AdditionalData({key: keccak256(abi.encode(calls[0])), value: abi.encode(0)}); - hintdices[1] = AdditionalData({key: keccak256(abi.encode(calls[1])), value: abi.encode(1)}); - - callbreaker.populateHintdicesHarness(abi.encode(hintdices)); - uint256[] memory indices = callbreaker.getCallIndex(calls[0]); assertEq(indices.length, calls.length); diff --git a/test/Laminator.t.sol b/test/Laminator.t.sol index 061b108..f01f8a7 100644 --- a/test/Laminator.t.sol +++ b/test/Laminator.t.sol @@ -189,7 +189,7 @@ contract LaminatorTest is Test { function testDelayedPushToProxy3delay1rollFails() public { // push sequence number 0. it should emit 42. uint256 val = 42; - CallObject[] memory callObjs; + CallObject[] memory callObjs = new CallObject[](1); callObjs[0] = CallObject({ amount: 0, addr: address(dummy), @@ -214,7 +214,7 @@ contract LaminatorTest is Test { laminator.harness_getOrCreateProxy(address(this)); uint256 val = 42; - CallObject[] memory callObjs; + CallObject[] memory callObjs = new CallObject[](1); callObjs[0] = CallObject({ amount: 0, addr: address(dummy), @@ -438,7 +438,7 @@ contract LaminatorTest is Test { // ensure executions called directly to proxy as a random address don't work function testExecuteAsRandomAddress() public { laminator.harness_getOrCreateProxy(address(this)); - CallObject[] memory callObjs; + CallObject[] memory callObjs = new CallObject[](1); callObjs[0] = CallObject({ amount: 0, addr: address(dummy), @@ -472,7 +472,7 @@ contract LaminatorTest is Test { // ensure executions as the owner directly into the proxy contract do NOT work function testExecuteAsOwner() public { laminator.harness_getOrCreateProxy(address(this)); - CallObject[] memory callObjs; + CallObject[] memory callObjs = new CallObject[](1); callObjs[0] = CallObject({ amount: 0, addr: address(dummy), @@ -505,7 +505,7 @@ contract LaminatorTest is Test { // ensure executions as random address through the laminator do not work function testExecuteAsRandomAddressFromLaminator() public { laminator.harness_getOrCreateProxy(address(this)); - CallObject[] memory callObjs; + CallObject[] memory callObjs = new CallObject[](1); callObjs[0] = CallObject({ amount: 0, addr: address(dummy), @@ -522,7 +522,7 @@ contract LaminatorTest is Test { // ensure executions as laminator through the laminator do work function testExecuteAsLaminatorAddressFromLaminator() public { laminator.harness_getOrCreateProxy(address(this)); - CallObject[] memory callObjs; + CallObject[] memory callObjs = new CallObject[](1); callObjs[0] = CallObject({ amount: 0, addr: address(dummy), diff --git a/test/contracts/CallBreakerHarness.sol b/test/contracts/CallBreakerHarness.sol index 281dd94..37653c8 100644 --- a/test/contracts/CallBreakerHarness.sol +++ b/test/contracts/CallBreakerHarness.sol @@ -32,10 +32,6 @@ contract CallBreakerHarness is CallBreaker { _populateAssociatedDataStore(associatedData); } - function populateHintdicesHarness(bytes memory encodedData) public { - _populateHintdices(encodedData); - } - function insertIntoHintdicesHarness(bytes32 key, uint256 value) public { hintdicesStore[key].push(value); } diff --git a/test/examples/DeFi/MockFlashLoan.sol b/test/examples/DeFi/MockFlashLoan.sol index bf4364d..fa0e492 100644 --- a/test/examples/DeFi/MockFlashLoan.sol +++ b/test/examples/DeFi/MockFlashLoan.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.26; import {IERC20} from "test/utils/interfaces/IMintableERC20.sol"; +import "src/TimeTypes.sol"; interface IFlashLoanBorrower { function onFlashLoan( @@ -10,7 +11,7 @@ interface IFlashLoanBorrower { uint256 amount1, address token2, uint256 amount2, - bytes calldata data + CallObject[] calldata callObjs ) external returns (bool); } @@ -33,7 +34,7 @@ contract MockFlashLoan { return (dai.balanceOf(address(this)), weth.balanceOf(address(this))); } - function flashLoan(address receiver, uint256 daiAmount, uint256 wethAmount, bytes calldata data) + function flashLoan(address receiver, uint256 daiAmount, uint256 wethAmount, CallObject[] calldata callObjs) external returns (bool) { @@ -41,7 +42,7 @@ contract MockFlashLoan { require(weth.transfer(receiver, wethAmount), "Insufficient usdt liquidity"); // Call the borrower's onFlashLoan function once (consolidated) - IFlashLoanBorrower(receiver).onFlashLoan(msg.sender, address(dai), daiAmount, address(weth), wethAmount, data); + IFlashLoanBorrower(receiver).onFlashLoan(msg.sender, address(dai), daiAmount, address(weth), wethAmount, callObjs); // Fetch the amount + fee via transferFrom require(dai.transferFrom(receiver, address(this), daiAmount), "Loan repayment failed"); diff --git a/test/solve-lib/DeFi/FlashLoanLib.sol b/test/solve-lib/DeFi/FlashLoanLib.sol index c19d62b..1a388ac 100644 --- a/test/solve-lib/DeFi/FlashLoanLib.sol +++ b/test/solve-lib/DeFi/FlashLoanLib.sol @@ -4,7 +4,6 @@ pragma solidity 0.8.26; import {FlashLoanData} from "src/CallBreakerTypes.sol"; import {Laminator, SolverData} from "src/lamination/Laminator.sol"; import "src/timetravel/CallBreaker.sol"; -import "src/timetravel/SmarterContract.sol"; import "test/examples/DeFi/MockDaiWethPool.sol"; import "test/examples/DeFi/MockFlashLoan.sol"; import "test/utils/MockERC20Token.sol"; @@ -138,14 +137,7 @@ contract FlashLoanLib { AdditionalData({key: keccak256(abi.encodePacked("tipYourBartender")), value: abi.encodePacked(filler)}); associatedData[1] = AdditionalData({key: keccak256(abi.encodePacked("pullIndex")), value: abi.encode(laminatorSequenceNumber)}); - - AdditionalData[] memory hintdices = new AdditionalData[](5); - hintdices[0] = AdditionalData({key: keccak256(abi.encode(callObjs[0])), value: abi.encode(0)}); - hintdices[1] = AdditionalData({key: keccak256(abi.encode(callObjs[1])), value: abi.encode(1)}); - hintdices[2] = AdditionalData({key: keccak256(abi.encode(callObjs[2])), value: abi.encode(2)}); - hintdices[3] = AdditionalData({key: keccak256(abi.encode(callObjs[3])), value: abi.encode(3)}); - hintdices[4] = AdditionalData({key: keccak256(abi.encode(callObjs[4])), value: abi.encode(4)}); - + callbreaker.executeAndVerify( callObjs, returnObjs, From 93861ec0eda910ff35d936debb8298b854d68f46 Mon Sep 17 00:00:00 2001 From: mevtxn Date: Wed, 27 Nov 2024 15:45:38 +0530 Subject: [PATCH 8/8] chore: update flashLoan function to take input data as bytes --- src/interfaces/IFlashLoan.sol | 3 +-- src/timetravel/CallBreaker.sol | 16 ++++++++++------ test/examples/DeFi/MockFlashLoan.sol | 7 +++---- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/interfaces/IFlashLoan.sol b/src/interfaces/IFlashLoan.sol index 913f96b..559d64f 100644 --- a/src/interfaces/IFlashLoan.sol +++ b/src/interfaces/IFlashLoan.sol @@ -1,9 +1,8 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.26; -import "../TimeTypes.sol"; interface IFlashLoan { - function flashLoan(address receiver, uint256 amountA, uint256 amountB, CallObject[] calldata callObjs) + function flashLoan(address receiver, uint256 amountA, uint256 amountB, bytes memory data) external returns (bool); } diff --git a/src/timetravel/CallBreaker.sol b/src/timetravel/CallBreaker.sol index 3482f13..dc23a06 100644 --- a/src/timetravel/CallBreaker.sol +++ b/src/timetravel/CallBreaker.sol @@ -67,7 +67,8 @@ contract CallBreaker is CallBreakerStorage { AdditionalData[] calldata associatedData ) external payable onlyPortalClosed { CallObject[] memory calls = _setupExecutionData(callsBytes, returnsBytes, associatedData); - _executeAndVerifyCalls(calls); + bytes memory data = abi.encode(calls); + _executeAndVerifyCalls(data); } /// @notice fetches flash loan before executing and verifying call objects who might use the loaned amount @@ -84,8 +85,9 @@ contract CallBreaker is CallBreakerStorage { FlashLoanData calldata flashLoanData ) external payable onlyPortalClosed { _setupExecutionData(callObjs, returnsBytes, associatedData); + bytes memory data = abi.encode(callObjs); IFlashLoan(flashLoanData.provider).flashLoan( - address(this), flashLoanData.amountA, flashLoanData.amountB, callObjs + address(this), flashLoanData.amountA, flashLoanData.amountB, data ); } @@ -95,7 +97,7 @@ contract CallBreaker is CallBreakerStorage { * @param amountA The amount of tokens lent. * @param tokenB The second loan currency. * @param amountB The amount of tokens lent. - * @param calls The calls to be executed + * @param data The encoded calls to be executed * @return true if the function executed successfully */ function onFlashLoan( @@ -104,11 +106,11 @@ contract CallBreaker is CallBreakerStorage { uint256 amountA, address tokenB, uint256 amountB, - CallObject[] calldata calls + bytes memory data ) external onlyPortalOpen returns (bool) { emit CallBreakerFlashFunds(tokenA, amountA, tokenB, amountB); - _executeAndVerifyCalls(calls); + _executeAndVerifyCalls(data); IERC20(tokenA).approve(msg.sender, amountA); IERC20(tokenB).approve(msg.sender, amountB); return true; @@ -238,7 +240,8 @@ contract CallBreaker is CallBreakerStorage { return calls; } - function _executeAndVerifyCalls(CallObject[] memory calls) internal { + function _executeAndVerifyCalls(bytes memory callData) internal { + CallObject[] memory calls = abi.decode(callData, (CallObject[])); uint256 l = calls.length; for (uint256 i = 0; i < l; i++) { _setCurrentlyExecutingCallIndex(i); @@ -277,6 +280,7 @@ contract CallBreaker is CallBreakerStorage { callStore.push().store(calls[i]); returnStore.push(returnValues[i]); + // Populating hintdices value while setting execution data bytes32 key = keccak256(abi.encode(calls[i])); hintdicesStoreKeyList.push(key); hintdicesStore[key].push(i); diff --git a/test/examples/DeFi/MockFlashLoan.sol b/test/examples/DeFi/MockFlashLoan.sol index fa0e492..25ef82a 100644 --- a/test/examples/DeFi/MockFlashLoan.sol +++ b/test/examples/DeFi/MockFlashLoan.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.26; import {IERC20} from "test/utils/interfaces/IMintableERC20.sol"; -import "src/TimeTypes.sol"; interface IFlashLoanBorrower { function onFlashLoan( @@ -11,7 +10,7 @@ interface IFlashLoanBorrower { uint256 amount1, address token2, uint256 amount2, - CallObject[] calldata callObjs + bytes calldata data ) external returns (bool); } @@ -34,7 +33,7 @@ contract MockFlashLoan { return (dai.balanceOf(address(this)), weth.balanceOf(address(this))); } - function flashLoan(address receiver, uint256 daiAmount, uint256 wethAmount, CallObject[] calldata callObjs) + function flashLoan(address receiver, uint256 daiAmount, uint256 wethAmount, bytes memory data) external returns (bool) { @@ -42,7 +41,7 @@ contract MockFlashLoan { require(weth.transfer(receiver, wethAmount), "Insufficient usdt liquidity"); // Call the borrower's onFlashLoan function once (consolidated) - IFlashLoanBorrower(receiver).onFlashLoan(msg.sender, address(dai), daiAmount, address(weth), wethAmount, callObjs); + IFlashLoanBorrower(receiver).onFlashLoan(msg.sender, address(dai), daiAmount, address(weth), wethAmount, data); // Fetch the amount + fee via transferFrom require(dai.transferFrom(receiver, address(this), daiAmount), "Loan repayment failed");