πSystem Flow
Users send preconfirmation requests to the preconfer
Preconfirmers review, accept, or reject requests based on the conditions and potential profitability.
The preconfer simulates the
tipTx
by calling a designated function on the LubanCore contract to check if the user has sufficient locked funds in the LubanEscrow.The preconfer assesses the risk and profitability based on the base fee forecast algorithm and the requested block number.
The preconfer forwards the preconf request, along with other metadata, to the opt-in proposer via Commit-Boost to request proposer signature.
If accepted, the preconfer signs the
initSignature
and populates thepreconferSignature
field to signal commitment. The proposer also signs theinitSignature
and populates theproposerSignature
field:Before the specified block number, the preconfer can call the
exhaust()
function to void the commitment and protect against user griefing or transactions exceeding the gas limit.The
exhaust()
function iteratively burns the gas that would have been required to execute the user's transaction.Calling
exhaust()
only allows the preconfer to receive theprePayment
, forgoing theafterPayment
.Users should ideally share the
preconfTx
with the preconfer sufficiently early to avoid the preconfer calling theexhaust()
function6 seconds into the block, the preconfer should share the entire list of
preconfTx
for the current block to a Commit-Boost aware relay:With the full list of
preconfTx
, the relay should only accept blocks that contain thepreconfTx
.The challenge mechanism works as before, with the exception that calling the
exhaust()
function exempts a preconfer from being slashed.
Sample PreconfRequest
{
"tipTx": {
"gasLimit": 100000,
"from": "0xUserAddress",
"to": "0xPreconferAddress",
"prePay": 1000000000000000000,
"afterPay": 2000000000000000000,
"nonce": 1
},
"prefConditions": {
"inclusionMetaData": {
"startingBlockNumber": 1000
},
"blockNumber": 1001
},
"preconfTx": {
"to": "0xContractAddress",
"value": 0,
"callData": "0x1234567890",
"ethTransfer": false
},
"initSignature": "0xUserSignature",
"preconferSignature": "0xPreconferSignature",
"proposerSignature": "0xProposerSignature"
}
Smart Contract Interface
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
interface ILubanCore {
/*//////////////////////////////////////////////////////
STRUCTS
//////////////////////////////////////////////////////*/
struct TipTx {
uint256 gasLimit;
address from;
address to;
uint256 prePay;
uint256 afterPay;
uint256 nonce;
}
struct PreconfTx {
address to;
uint256 value;
bytes callData;
bool ethTransfer;
}
struct InclusionMeta {
uint256 startingBlockNumber;
}
struct PreconfConditions {
InclusionMeta inclusionMetaData;
uint256 blockNumber;
}
struct PreconfRequest {
TipTx tipTx;
PreconfConditions prefConditions;
PreconfTx preconfTx;
bytes tipTxSignature;
bytes initSignature;
bytes preconferSignature;
bytes proposerSignature;
}
enum PreconfRequestStatus {
NonInitiated,
Exhausted,
Executed,
Collected
}
/*//////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////*/
function settleRequest(PreconfRequest calldata preconfReq) external payable;
function exhaust(TipTx calldata tipTx, bytes calldata userSignature, bytes calldata preconferSignature) external;
function getTipTxHash(ILubanCore.TipTx calldata tipTx) external view returns (bytes32);
function handlePayment(uint256 amount, address preconferAddr, bytes calldata preconferSig) external payable;
function getTipTxAndPreconfConditionsHash(
TipTx calldata tipTx,
PreconfConditions calldata preconfConditions
)
external
view
returns (bytes32);
function getPreconfRequestStatus(bytes32 preconferSignature) external view returns (PreconfRequestStatus);
function collectTip(address preconfer, bytes32 preconferSignature) external;
}
Last updated