@unruggable/gateways
Version:
Trustless Ethereum Multichain CCIP-Read Gateway
134 lines (133 loc) • 4.79 kB
JavaScript
import { AbstractRollup, } from '../rollup.mjs';
import { Contract } from 'ethers/contract';
import { CHAINS } from '../chains.mjs';
import { EthProver } from '../eth/EthProver.mjs';
import { ABI_CODER } from '../utils.mjs';
import { Interface } from 'ethers/abi';
import { CachedValue } from '../cached.mjs';
// https://github.com/taikoxyz/taiko-mono/
// https://docs.taiko.xyz/network-reference/differences-from-ethereum
// https://status.taiko.xyz/
// https://x.com/taikoxyz/status/1923698062503051483
// https://taiko.mirror.xyz/pIchmo0E-DfSySCzL52BFbus54Z3XJEO0k0Ptqqpm_I
// https://docs.taiko.xyz/taiko-alethia-protocol/codebase-analysis/taikol1-contract
const ROLLUP_ABI = new Interface([
`function getConfig() view returns (tuple(
uint64 chainId,
uint64 blockMaxProposals,
uint64 blockRingBufferSize,
uint64 maxBlocksToVerify,
uint32 blockMaxGasLimit,
uint96 livenessBond,
uint8 stateRootSyncInternal,
bool checkEOAForCalldataDA
))`,
`function getLastSyncedTransition() view returns (uint64 batchId)`,
// `function getLastSyncedBlock() view returns (uint64 blockId, bytes32 blockHash, bytes32 stateRoot)`,
// `function getConfig() view returns (tuple(
// uint64 chainId,
// uint64 blockMaxProposals,
// uint64 blockRingBufferSize,
// uint64 maxBlocksToVerify,
// uint32 blockMaxGasLimit,
// uint96 livenessBond,
// uint8 stateRootSyncInternal,
// bool checkEOAForCalldataDA
// ))`,
//`function getLastVerifiedTransition() view returns (uint64)`,
// `function getLastSyncedTransition() view returns (
// uint64 batchId,
// uint64 blockId,
// (
// bytes32 parentHash,
// bytes32 blockHash,
// bytes32 stateRoot,
// address prover,
// bool inProvingWindow,
// uint48 createdAt
// ) tr
// )`,
// `function getBatch(uint64 batchId) view returns ((
// bytes32 metaHash,
// uint64 lastBlockId,
// uint96 reserved3,
// uint96 livenessBond,
// uint64 batchId,
// uint64 lastBlockTimestamp,
// uint64 anchorBlockId,
// uint24 nextTransitionId,
// uint8 reserved4,
// uint24 verifiedTransitionId
// ))`,
// `function getTransitionByParentHash(uint64 batchId, bytes32 parentHash) view returns ((
// bytes32 parentHash,
// bytes32 blockHash,
// bytes32 stateRoot,
// address prover,
// bool inProvingWindow,
// uint48 createdAt
// ))`,
//`event BlockVerified(uint256 blockId, address verifier, bytes32 stateRoot)`,
// `event TransitionProvedV2(
// uint256 indexed blockId,
// (
// bytes32 parentHash,
// bytes32 blockHash,
// bytes32 stateRoot,
// address prover,
// bool inProvingWindow,
// uint48 createdAt
// ) tr,
// address prover,
// uint96 validityBond,
// uint16 tier,
// uint64 proposedIn
// )`,
]);
export class TaikoRollup extends AbstractRollup {
commitSpan;
// https://docs.taiko.xyz/network-reference/mainnet-addresses
static mainnetConfig = {
chain1: CHAINS.MAINNET,
chain2: CHAINS.TAIKO,
TaikoL1: '0x06a9Ab27c7e2255df1815E6CC0168d7755Feb19a',
};
static heklaConfig = {
chain1: CHAINS.HOLESKY,
chain2: CHAINS.TAIKO_HEKLA,
TaikoL1: '0x79C9109b764609df928d16fC4a91e9081F7e87DB',
};
TaikoL1;
commitStep = new CachedValue(async () => {
const cfg = await this.TaikoL1.getConfig();
return cfg.stateRootSyncInternal * BigInt(this.commitSpan);
}, Infinity);
constructor(providers, config, commitSpan = 1) {
super(providers);
this.commitSpan = commitSpan;
this.TaikoL1 = new Contract(config.TaikoL1, ROLLUP_ABI, this.provider1);
}
fetchLatestCommitIndex() {
return this.TaikoL1.getLastSyncedTransition({
blockTag: this.latestBlockTag,
});
}
async _fetchParentCommitIndex(commit) {
return commit.index - (await this.commitStep.get());
}
async _fetchCommit(index) {
const prover = new EthProver(this.provider2, index);
const { parentHash } = await prover.fetchBlock();
return { index, prover, parentHash };
}
encodeWitness(commit, proofSeq) {
return ABI_CODER.encode(['(uint256, bytes32, bytes[], bytes)'], [[commit.index, commit.parentHash, proofSeq.proofs, proofSeq.order]]);
}
windowFromSec(sec) {
// taiko is a based rollup
const avgBlockSec = 16; // block every block 12-20 sec
return Math.ceil(sec / avgBlockSec); // units of blocks
// time is now available onchain
//return sec;
}
}