Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

feat: new batch dispatch simulate decoded #183

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions contracts/modules/Exec.sol
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,29 @@ contract Exec is BaseLogic {
revert("e/batch/simulation-did-not-revert");
}

/// @notice Call batch dispatch and catch the revert and parse it to EulerBatchItemResponse[]
/// @param items List of operations to execute
/// @param deferLiquidityChecks List of user accounts to defer liquidity checks for
/// @dev During simulation all batch items are executed, regardless of the `allowError` flag
function batchDispatchSimulateDecoded(EulerBatchItem[] calldata items, address[] calldata deferLiquidityChecks) external reentrantOK returns (EulerBatchItemResponse[] memory simulation) {
address msgSender = unpackTrailingParamMsgSender();
bytes memory data = abi.encodeWithSelector(Exec.batchDispatchSimulate.selector, items, deferLiquidityChecks);
bytes memory inputWrapped = abi.encodePacked(data, uint160(msgSender), uint160(msg.sender)); // msg.sender is the proxy address
(, bytes memory reason) = moduleLookup[MODULEID__EXEC].delegatecall(inputWrapped);

bytes4 errorSelector = bytes4(reason);
if(errorSelector != BatchDispatchSimulation.selector){
revertBytes(reason);
}
assembly {
reason := add(reason, 0x4)
}
simulation = abi.decode(
reason,
(EulerBatchItemResponse[])
);
}


// Average liquidity tracking

Expand Down
20 changes: 20 additions & 0 deletions test/batch.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,26 @@ et.testSet({
]
})

.test({
desc: "new batch simulate",
actions: ctx => [
{ send: 'eTokens.eTST.deposit', args: [0, et.eth(1)], },
{ send: 'tokens.TST.configure', args: ['transfer/revert', []] },
{ action: 'sendBatch', simulate: true, deferLiquidityChecks: [ctx.wallet.address], batch: [
{ send: 'eTokens.eTST.withdraw', args: [0, et.eth(1)], },
], onResult: r => {
et.expect(r[0].success).to.equal(false);
// safeTransferFrom adds additional error bytes that we need to remove
// first 4 bytes are the error selector
// second 32 bytes are the pointer for the start of error msg
// third 32 bytes are the length of the error msg
// then we have 4 bytes of again the Error(string) selector = 08c379a0
// size = 4 + 32 + 32 + 4 = 72 which equals 144 length slice + 2 for 0x = 146
const msg = utils.defaultAbiCoder.decode(["string"], "0x" + r[0].result.slice(146))[0];
et.expect(msg).to.equal("revert behaviour")
}},
]
})


.run();
7 changes: 1 addition & 6 deletions test/lib/eTestLib.js
Original file line number Diff line number Diff line change
Expand Up @@ -1455,12 +1455,7 @@ class TestSet {
let result;

if (action.simulate) {
try {
await ctx.contracts.exec.connect(from).callStatic.batchDispatchSimulate(items, action.deferLiquidityChecks || []);
} catch (e) {
if (e.errorName !== 'BatchDispatchSimulation') throw e;
result = e.errorArgs.simulation;
}
result = await ctx.contracts.exec.connect(from).callStatic.batchDispatchSimulateDecoded(items, action.deferLiquidityChecks || []);
} else {
let tx = await ctx.contracts.exec.connect(from).batchDispatch(items, action.deferLiquidityChecks || []);
result = await tx.wait();
Expand Down