Skip to content

Commit

Permalink
Add L1FeeProvider for rollups with smart contract who can provide L1 fee
Browse files Browse the repository at this point in the history
  • Loading branch information
esen committed Aug 4, 2022
1 parent 65a006a commit 0980ae9
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ object ContractMethodHelper {
}
is ByteArray -> {
data += pad(unsignedBigIntergerToByteArray(BigInteger.valueOf(arguments.size * 32L + arraysData.size)))
arraysData += pad(BigInteger.valueOf(data.size.toLong()).toByteArray()) + data
arraysData += pad(BigInteger.valueOf(data.size.toLong()).toByteArray()) + argument
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,38 +36,51 @@ class TransactionBuilder(
)
}

fun encode(rawTransaction: RawTransaction, signature: Signature): ByteArray {
return when (rawTransaction.gasPrice) {
is GasPrice.Eip1559 -> {
val encodedTransaction = RLP.encodeList(
RLP.encodeInt(chainId),
RLP.encodeLong(rawTransaction.nonce),
RLP.encodeLong(rawTransaction.gasPrice.maxPriorityFeePerGas),
RLP.encodeLong(rawTransaction.gasPrice.maxFeePerGas),
RLP.encodeLong(rawTransaction.gasLimit),
RLP.encodeElement(rawTransaction.to.raw),
RLP.encodeBigInteger(rawTransaction.value),
RLP.encodeElement(rawTransaction.data),
RLP.encode(arrayOf<Any>()),
RLP.encodeByte(signature.v),
RLP.encodeBigInteger(signature.r.toBigInteger()),
RLP.encodeBigInteger(signature.s.toBigInteger())
)
"0x02".hexStringToByteArray() + encodedTransaction
}
is GasPrice.Legacy -> {
RLP.encodeList(
RLP.encodeLong(rawTransaction.nonce),
RLP.encodeLong(rawTransaction.gasPrice.legacyGasPrice),
RLP.encodeLong(rawTransaction.gasLimit),
RLP.encodeElement(rawTransaction.to.raw),
RLP.encodeBigInteger(rawTransaction.value),
RLP.encodeElement(rawTransaction.data),
RLP.encodeByte(signature.v),
RLP.encodeBigInteger(signature.r.toBigInteger()),
RLP.encodeBigInteger(signature.s.toBigInteger())
fun encode(rawTransaction: RawTransaction, signature: Signature): ByteArray =
encode(rawTransaction, signature, chainId)

companion object {

fun encode(rawTransaction: RawTransaction, signature: Signature?, chainId: Int = 1): ByteArray {
val signatureArray = signature?.let {
arrayOf(
RLP.encodeByte(it.v),
RLP.encodeBigInteger(it.r.toBigInteger()),
RLP.encodeBigInteger(it.s.toBigInteger())
)
} ?: arrayOf()

return when (rawTransaction.gasPrice) {
is GasPrice.Eip1559 -> {
val elements = arrayOf(
RLP.encodeInt(chainId),
RLP.encodeLong(rawTransaction.nonce),
RLP.encodeLong(rawTransaction.gasPrice.maxPriorityFeePerGas),
RLP.encodeLong(rawTransaction.gasPrice.maxFeePerGas),
RLP.encodeLong(rawTransaction.gasLimit),
RLP.encodeElement(rawTransaction.to.raw),
RLP.encodeBigInteger(rawTransaction.value),
RLP.encodeElement(rawTransaction.data),
RLP.encode(arrayOf<Any>())
) + signatureArray

val encodedTransaction = RLP.encodeList(*elements)
"0x02".hexStringToByteArray() + encodedTransaction
}
is GasPrice.Legacy -> {
val elements = arrayOf(
RLP.encodeLong(rawTransaction.nonce),
RLP.encodeLong(rawTransaction.gasPrice.legacyGasPrice),
RLP.encodeLong(rawTransaction.gasLimit),
RLP.encodeElement(rawTransaction.to.raw),
RLP.encodeBigInteger(rawTransaction.value),
RLP.encodeElement(rawTransaction.data)
) + signatureArray

RLP.encodeList(*elements)
}
}
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.horizontalsystems.ethereumkit.core.rollup

import io.horizontalsystems.ethereumkit.contracts.ContractMethod
import io.horizontalsystems.ethereumkit.core.EthereumKit
import io.horizontalsystems.ethereumkit.core.TransactionBuilder
import io.horizontalsystems.ethereumkit.models.Address
import io.horizontalsystems.ethereumkit.models.GasPrice
import io.horizontalsystems.ethereumkit.models.RawTransaction
import io.horizontalsystems.ethereumkit.spv.core.toBigInteger
import io.reactivex.Single
import java.math.BigInteger

class L1FeeProvider(
private val evmKit: EthereumKit,
private val contractAddress: Address
) {

class L1FeeMethod(val transaction: ByteArray) : ContractMethod() {
override val methodSignature = "getL1Fee(bytes)"
override fun getArguments() = listOf(transaction)
}

fun getL1Fee(gasPrice: GasPrice, gasLimit: Long, to: Address, value: BigInteger, data: ByteArray, nonce: Long?): Single<BigInteger> {
val rawTransaction = RawTransaction(gasPrice, gasLimit, to, value, nonce ?: 1, data)
val encoded = TransactionBuilder.encode(rawTransaction, null, evmKit.chain.id)
val data = L1FeeMethod(encoded).encodedABI()

return evmKit.call(contractAddress, data)
.map { it.sliceArray(IntRange(0, 31)).toBigInteger() }
}

}

0 comments on commit 0980ae9

Please sign in to comment.