Arbitrage rETH mint/burn with minipool deposit/withdrawal
How to? Here are the steps... Message me on the RocketPool Discord if you have any problems!
- Try almost creating the minipool the normal way with the Rocketpool
smartnode (>= 1.7.0). Stop before the final
ARE YOU SURE...
prompt and cancel it. - Ensure your node's RPC port is exposed locally as described here.
- Install the requirements on your node machine:
nodejs
(>= 18), andnpm
. - Clone this repo (
git clone https://github.com/xrchz/rocketarb
),cd rocketarb
, andnpm install
to download the js dependencies. - Run
./rocketarb.js
. It should be fine with no arguments.- Pass the
--help
to see more options if something goes wrong. - A typical flow might involve, first:
./rocketarb.js --dry-run
- Then if that succeeds without any reverts:
./rocketarb.js --resume-deposit
- Pass the
If you have used rocketarb
before and want to upgrade to the latest version,
you can simply git pull
your clone of this repo.
- Ask the smartnode to create a minipool deposit transaction from your node account.
- Create a transaction to call the rocketarb contract, which will flash loan 16 ETH, deposit it in the Rocket Pool deposit pool (using the newly created space from the minipool deposit), sell the minted rETH using 1Inch, repay the flash loan, and send any profit back to your node account.
- Submit the two transactions above in a bundle using Flashbots.
This way you get to benefit from the rETH premium by the space temporarily created in the deposit pool by your new minipool.
- The smartnode needs to be at least version 1.7.0.
- Try
--rpc http://<your node local ip>:8545
if the default (http://localhost:8545
) does not work. - You can try submitting the Flashbots bundle again (in case it failed) without
recreating the transactions. Use
--resume-deposit
to only recreate the arb transaction (with fresh 1Inch swap data); use the--resume
option to recreate neither (i.e., reuse both transactions). (The bundle gets saved inbundle.json
by default.) - The gas fee needs to be attractive enough for Flashbots to accept the bundle:
the target block base fee per gas is burned and the block proposer receives
any additional fee per gas up to the specified maximum priority fee per gas
limited by the specified maximum fee per gas. The priority fee is what makes
a bundle attractive.
rocketarb
uses the same maximum fees for both the deposit and arbitrage transactions, and the total gas will be about 2.7 million (approximately: 2 million for the deposit, 800k for the arbitrage -- these vary and can be hard to predict exactly). rocketarb
will try to ensure to refund at least some (2.8M gas worth by default, change it with the--gas-refund
option) of your gas costs with the arbitrage profits. This is ensured by making the arbitrage transaction revert (not enough profit
) if it does not produce at least this much profit.- If your bundle is not getting included (
BlockPassedWithoutInclusion
) most likely the transactions are reverting with some failure (try the--dry-run
option to investigate), or the gas fees are too low for the current base fee. - If the simulation returns
execution reverted
without further details, probably the gas limit for the arb transaction is too low; you could try increasing it with the--gas-limit
option (and you might also like to increase--gas-refund
accordingly). - Every time we ask the smartnode for a deposit transaction, it increments its internal validator index (saved in your node's wallet file). If you need to re-run (e.g., to use a different maximum fee per gas) and don't want to waste the index, you can manually decrement it by editing the wallet file. Wasting indices is not a problem for your node, however - the generated validator keys for an unused index will simply remain unused.
- It is safe to unexpose your node's RPC port after you're done with
rocketarb
if you prefer leaving it hidden.
- Pass the
--no-flash-loan
option to use capital (e.g., 16 ETH, or whatever the--amount
of your minipool deposit is) in your node account instead of a flash loan. - Why do this? It could reduce the total gas cost, and thereby increase
profits. You can control the gas limits with the various
--X-gas-limit
options. - Warning: with
--no-flash-loan
there is no check for minimum profit, i.e., the--gas-refund
option is ignored. Check the premium is healthy (e.g,. >1%) with the--premium
option first. - By default
rocketarb
tries to arb both the minipool deposit amount and any free space in the deposit pool. If you do not have enough capital to additionally cover the existing free space in the deposit pool, pass the--no-use-dp
option.
By default rocketarb
uses the smartnode daemon to sign all transactions. For
security, you can instead use the --daemon <program>
argument to avoid
running rocketarb
on your node. The <program>
supplied will be called in
two ways by rocketarb
, with different arguments:
-
<program> api node deposit <amount> <commission> <salt> false
The program should output a signed minipool deposit transaction (without any leading
0x
), just as the smartnode daemon api would output with these arguments. (You could run the smartnode daemon once first to get the data then save it for further use byrocketarb
.) -
<program> api node sign <inputSignedTx>
The program should output JSON for an object containing two keys:
{status: "success", signedData: <signedTx>}
wheresignedTx
is a version of the transaction represented by<inputSignedTx>
signed by the account you want to do the non-deposit transactions with.<inputSignedTx>
is a signed transaction (without the leading0x
) signed by a random account.signedTx
should be a string that includes a leading0x
.