mev-geth
mev-geth copied to clipboard
New RPC endpoint: eth_balanceDeltaBundle
Rationale
We should find a better name for this, but the idea is that a bundle often changes token balances (ETH, ERC20, NFT's, etc) and while it's possible to "sandwich" your bundle with balanceOf
calls for specific tokens you expect to transfer within a bundle, for a specific account, we could automatically figure out which tokens were moved. We should create an RPC endpoint that returns a report of all token balances that were modified as a result of this bundle running in simulation.
When conducting whitehat rescues, especially for a brand new rescue type, this is one of the most sensitive issues: your custom code worked enough to rescue assets, but has a bug that locks assets or transfers to the wrong place. Having bundle execution distilled to a set of balance changes would help prevent accidental fund loss by providing positive confirmation of token flow.
If this could be combined with Flashbots protect RPC endpoint, we could easily prevent certain behaviors from propagating through our RPC (like TokenOops).
Implementation
I think this would be a separate endpoint from callBundle
, as that should be as fast as possible, and this implementation would require at LEAST two simulation passes and many extraneous storage lookups.
Would be fine to either use signed or unsigned transactions
It would be great to make this as generic as possible and not limit it to certain standards i.e. ERC20 / ERC721.
My API proposal would be something like:
method: 'eth_balanceDeltaBundle'
params: [{
balanceDelta: [
// This should return a uint256, for a future PR, we could add a "formatter" akin to the debug_trace*
// JavaScript runtime environment
{ address: '0x0...', data: '0x0....' }
],
txs: [ ], // signed or unsigned txs, same as callBundle
stateBlockNumber: 1,
blockNumber: 1
}]
For now we can just assume all balances is uint256
, and the response should be roughly:
result: {
balanceDelta: [
{ delta: 100 }
],
txs: [ ... ] // normal callBundle tx return
}
Let me know your thoughts
For now we can just assume all balances is
uint256
I like the simplicity of this api. By convention we can deem a null data field to return the ETH balance.
Care must be taken for the result to be an array of signed 256 bit integers.
An even more generalized api would be a pre-flight and post-flight multicall. Though this is probably overkill.
Something like this:
method: 'eth_balanceDeltaBundle'
params: [{
preCheck: [
{ address: '0x0...', data: '0x0....' }
],
postCheck: [
{ address: '0x0...', data: '0x0....' }
],
txs: [ ], // signed or unsigned txs, same as callBundle
stateBlockNumber: 1,
blockNumber: 1
}]
result: {
preCheck: [
{ result: '0x0....' }
],
postCheck: [
{ result: '0x0....' }
],
txs: [ ... ] // normal callBundle tx return
}