2021-08-22 19:23:30 +03:00
|
|
|
|
:: roller/send: send rollup tx
|
2021-05-13 18:21:35 +03:00
|
|
|
|
::
|
2021-08-04 16:53:57 +03:00
|
|
|
|
/- rpc=json-rpc, *dice
|
2021-05-13 18:21:35 +03:00
|
|
|
|
/+ naive, ethereum, ethio, strandio
|
|
|
|
|
::
|
|
|
|
|
::
|
|
|
|
|
|= args=vase
|
2021-05-21 16:07:08 +03:00
|
|
|
|
=+ !<(rpc-send-roll args)
|
2021-05-13 18:21:35 +03:00
|
|
|
|
=/ m (strand:strandio ,vase)
|
|
|
|
|
|^
|
|
|
|
|
^- form:m
|
2021-10-02 09:44:37 +03:00
|
|
|
|
:: =* not-sent (pure:m !>(%.n^next-gas-price))
|
2021-05-13 18:21:35 +03:00
|
|
|
|
::
|
2021-05-21 13:16:57 +03:00
|
|
|
|
=/ =address:ethereum (address-from-prv:key:ethereum pk)
|
2021-05-13 18:21:35 +03:00
|
|
|
|
;< expected-nonce=@ud bind:m
|
|
|
|
|
(get-next-nonce:ethio endpoint address)
|
|
|
|
|
:: if chain expects a different nonce, don't send this transaction
|
|
|
|
|
::
|
|
|
|
|
?. =(nonce expected-nonce)
|
2021-08-22 19:23:30 +03:00
|
|
|
|
~& [%unexpected-nonce nonce expected+expected-nonce]
|
2021-10-02 09:44:37 +03:00
|
|
|
|
(pure:m !>(%.n^[%not-sent %unexpected-nonce]))
|
2021-05-13 18:21:35 +03:00
|
|
|
|
:: if a gas-price of 0 was specified, fetch the recommended one
|
|
|
|
|
::
|
|
|
|
|
;< use-gas-price=@ud bind:m
|
|
|
|
|
?: =(0 next-gas-price) fetch-gas-price
|
|
|
|
|
(pure:(strand:strandio @ud) next-gas-price)
|
2021-06-14 18:21:57 +03:00
|
|
|
|
::
|
2021-06-15 08:22:55 +03:00
|
|
|
|
=/ batch-data=octs
|
|
|
|
|
%+ cad:naive 3
|
|
|
|
|
%+ roll txs
|
|
|
|
|
|= [=raw-tx:naive out=(list octs)]
|
|
|
|
|
%+ weld
|
|
|
|
|
out
|
|
|
|
|
:_ [raw.raw-tx ~]
|
|
|
|
|
(met 3 sig.raw-tx)^sig.raw-tx
|
|
|
|
|
:: each l2 signature is 65 bytes + XX bytes for the raw data
|
2021-06-14 18:21:57 +03:00
|
|
|
|
:: from the ethereum yellow paper:
|
2021-06-15 08:22:55 +03:00
|
|
|
|
:: gasLimit = G_transaction + G_txdatanonzero × dataByteLength
|
2021-06-14 18:21:57 +03:00
|
|
|
|
:: where
|
2021-06-15 08:22:55 +03:00
|
|
|
|
:: G_transaction = 21000 gas (base fee)
|
2021-06-14 18:21:57 +03:00
|
|
|
|
:: + G_txdatanonzero = 68 gas
|
2021-06-15 08:22:55 +03:00
|
|
|
|
:: * dataByteLength = (65 + raw) * (lent txs) bytes
|
2021-06-14 18:21:57 +03:00
|
|
|
|
::
|
|
|
|
|
:: TODO: enforce max number of tx in batch?
|
|
|
|
|
::
|
2021-06-15 08:22:55 +03:00
|
|
|
|
=/ gas-limit=@ud (add 21.000 (mul 68 p.batch-data))
|
2021-05-13 18:21:35 +03:00
|
|
|
|
:: if we cannot pay for the transaction, don't bother sending it out
|
|
|
|
|
::
|
|
|
|
|
=/ max-cost=@ud (mul gas-limit use-gas-price)
|
2021-05-29 15:22:33 +03:00
|
|
|
|
;< balance=@ud bind:m
|
|
|
|
|
(get-balance:ethio endpoint address)
|
|
|
|
|
?: (gth max-cost balance)
|
2021-08-22 19:23:30 +03:00
|
|
|
|
~& [%insufficient-roller-balance address]
|
2021-10-02 09:44:37 +03:00
|
|
|
|
(pure:m !>(%.n^[%not-sent %insufficient-roller-balance]))
|
2021-05-13 18:21:35 +03:00
|
|
|
|
::
|
2021-05-29 15:57:57 +03:00
|
|
|
|
::NOTE this fails the thread if sending fails, which in the app gives us
|
|
|
|
|
:: the "retry with same gas price" behavior we want
|
|
|
|
|
;< =response:rpc bind:m
|
|
|
|
|
%+ send-batch endpoint
|
2021-05-13 18:21:35 +03:00
|
|
|
|
=; tx=transaction:rpc:ethereum
|
|
|
|
|
(sign-transaction:key:ethereum tx pk)
|
|
|
|
|
:* nonce
|
|
|
|
|
use-gas-price
|
2021-06-14 18:21:57 +03:00
|
|
|
|
gas-limit
|
2021-05-13 18:21:35 +03:00
|
|
|
|
contract
|
|
|
|
|
0
|
2021-06-15 08:22:55 +03:00
|
|
|
|
q.batch-data
|
2021-05-13 18:21:35 +03:00
|
|
|
|
chain-id
|
|
|
|
|
==
|
2021-05-22 09:10:30 +03:00
|
|
|
|
%- pure:m
|
2021-10-02 09:44:37 +03:00
|
|
|
|
!> ^- (each @ud [term @t])
|
2021-09-01 12:01:39 +03:00
|
|
|
|
:: TODO: capture if the tx fails (e.g. Runtime Error: revert)
|
|
|
|
|
::
|
2021-10-02 09:44:37 +03:00
|
|
|
|
?+ -.response %.n^[%error 'unexpected rpc response']
|
|
|
|
|
%error %.n^[%error message.response]
|
2021-05-22 09:10:30 +03:00
|
|
|
|
:: TODO:
|
|
|
|
|
:: check that tx-hash in +.response is non-zero?
|
|
|
|
|
:: log tx-hash to getTransactionReceipt(tx-hash)?
|
|
|
|
|
:: enforce max here, or in app?
|
|
|
|
|
:: add five gwei to gas price of next attempt
|
|
|
|
|
::
|
|
|
|
|
%result %.y^(add use-gas-price 5.000.000.000)
|
|
|
|
|
==
|
2021-05-13 18:21:35 +03:00
|
|
|
|
::
|
|
|
|
|
::TODO should be distilled further, partially added to strandio?
|
|
|
|
|
++ fetch-gas-price
|
|
|
|
|
=/ m (strand:strandio @ud) ::NOTE return in wei
|
|
|
|
|
^- form:m
|
|
|
|
|
=/ =request:http
|
|
|
|
|
:* method=%'GET'
|
|
|
|
|
url='https://api.etherscan.io/api?module=gastracker&action=gasoracle'
|
|
|
|
|
header-list=~
|
|
|
|
|
~
|
|
|
|
|
==
|
|
|
|
|
;< ~ bind:m
|
|
|
|
|
(send-request:strandio request)
|
|
|
|
|
;< rep=(unit client-response:iris) bind:m
|
|
|
|
|
take-maybe-response:strandio
|
|
|
|
|
=* fallback
|
|
|
|
|
~& %fallback-gas-price
|
2021-06-24 17:38:54 +03:00
|
|
|
|
(pure:m 10.000.000.000)
|
2021-05-13 18:21:35 +03:00
|
|
|
|
?. ?& ?=([~ %finished *] rep)
|
|
|
|
|
?=(^ full-file.u.rep)
|
|
|
|
|
==
|
|
|
|
|
fallback
|
|
|
|
|
?~ jon=(de-json:html q.data.u.full-file.u.rep)
|
|
|
|
|
fallback
|
|
|
|
|
=; res=(unit @ud)
|
|
|
|
|
?~ res fallback
|
|
|
|
|
%- pure:m
|
|
|
|
|
(mul 1.000.000.000 u.res) ::NOTE gwei to wei
|
|
|
|
|
%. u.jon
|
|
|
|
|
=, dejs-soft:format
|
2021-05-21 13:16:57 +03:00
|
|
|
|
(ot 'result'^(ot 'FastGasPrice'^ni ~) ~)
|
2021-05-22 09:10:30 +03:00
|
|
|
|
::
|
|
|
|
|
++ send-batch
|
|
|
|
|
|= [endpoint=@ta batch=@ux]
|
|
|
|
|
=/ m (strand:strandio ,response:rpc)
|
|
|
|
|
^- form:m
|
|
|
|
|
=/ req=[(unit @t) request:rpc:ethereum]
|
|
|
|
|
[`'sendRawTransaction' %eth-send-raw-transaction batch]
|
|
|
|
|
;< res=(list response:rpc) bind:m
|
|
|
|
|
(request-batch-rpc-loose:ethio endpoint [req]~)
|
|
|
|
|
?: ?=([* ~] res)
|
|
|
|
|
(pure:m i.res)
|
|
|
|
|
%+ strand-fail:strandio
|
|
|
|
|
%unexpected-multiple-results
|
|
|
|
|
[>(lent res)< ~]
|
|
|
|
|
::
|
2021-05-13 18:21:35 +03:00
|
|
|
|
--
|