Skip to main content

Precompile Contracts

On top of a set of opcodes, EVM also offers advanced functionalities through precompiled contracts. These are special contracts bundled with EVM at fixed addresses that can be called with a determined gas. The gas is purely the contractual cost, neither the cost of the call itself nor the instructions to put the parameters in memory.

Precompiled contract addresses start from 1 and increment for each contract. New hardforks may introduce new precompiled contracts. Similar to the regular contracts, new contracts are called from opcodes with instructions, such as CALL.

For all precompiled contracts, inputs that are shorter than expected are assumed to be virtually padded with zeros at the end, whereas any surplus bytes at the end of inputs that are longer than expected are ignored.

The address precompile contract is described by the last 2 bytes:

Byte range [0..18]Byte range [18..20]
000000000000000000000000000000000000addr

EcRecover

ADDRESSMINIMUM GASINPUTOUTPUT
0x00000000000000000000000000000000000000013000hash, v, r, spublicAddress

EcRecover is a elliptic curve digital signature algorithm (ECDSA) public key recovery function. For details, see this page.

SHA2-256

ADDRESSMINIMUM GASINPUTOUTPUT
0x000000000000000000000000000000000000000260datahash

SHA2-256 is the hash function used in Bitcoin. For details, see this page

RIPEMD-160

ADDRESSMINIMUM GASINPUTOUTPUT
0x0000000000000000000000000000000000000003600datahash

A hash function. For details, see this page.

Identity

ADDRESSMINIMUM GASINPUTOUTPUT
0x000000000000000000000000000000000000000415datadata

Identity copies and returns input data. For details, see this page.

Modexp

ADDRESSMINIMUM GASINPUTOUTPUT
0x0000000000000000000000000000000000000005200Bsize, Esize, Msize, B, E, Mvalue

Modexp is an arbitrary-precision exponentiation under modulo. For details, see this page.

EcAdd

ADDRESSMINIMUM GASINPUTOUTPUT
0x0000000000000000000000000000000000000006150x1, x2, y1, y2x, y

EcAdd is the point addition (ADD) on the elliptic curve alt_bn128. For details, see this page.

EcMul

ADDRESSMINIMUM GASINPUTOUTPUT
0x00000000000000000000000000000000000000076000x1, x2, sx, y

EcMul is the scalar multiplication (MUL) on the elliptic curve alt_bn128. For details, see this page.

EcPairing

ADDRESSMINIMUM GASINPUTOUTPUT
0x000000000000000000000000000000000000000845000x1, y1, x2, y2, …, xk, yksuccess

EcPairing is the bilinear function on groups on the elliptic curve alt_bn128. For details, see this page.

Blake2f

ADDRESSMINIMUM GASINPUTOUTPUT
0x00000000000000000000000000000000000000090rounds, h, m, t, fh

Blake2f is the compression function F used in the BLAKE2 cryptographic hashing algorithm. For details, see this page.

GetHeader

ADDRESSMINIMUM GASINPUTOUTPUT
0x000000000000000000000000000000000000010242000hashheader view

Get the header of a relayed CKB block header by hash.

Inputs

Click here to view ABI
struct Input {
bytes32 hash;
}

Output

Click here to view ABI
struct Header {
uint32 version;
uint32 compactTarget;
uint64 timestamp;
uint64 number;
uint64 epoch;
bytes32 parentHash;
bytes32 transactionsRoot;
bytes32 proposalsHash;
bytes32 extraHash;
bytes32 dao;
uint128 nonce;
bytes extension;
bytes32 blockHash;
}

Example

Click here to view example
contract GetCkbHeader {
event GetHeaderEvent(CKBHeader);
event NotGetHeaderEvent();

int8 ret;

function getHeader(bytes32 blockHash) public returns (CKBHeader memory) {
address get_header_addr = address(0x0102);
(bool isSuccess, bytes memory res) = get_header_addr.staticcall(
abi.encode(blockHash)
);

CKBHeader memory header;
if (isSuccess) {
header = abi.decode(res, (CKBHeader));
emit GetHeaderEvent(header);
} else {
emit NotGetHeaderEvent();
}
return header;
}
}

GetCell

ADDRESSMINIMUM GASINPUTOUTPUT
0x000000000000000000000000000000000000010342000out pointcell info

Get the relayed cell information by out point.

Inputs

Click here to view ABI
struct OutPoint {
bytes32 txHash;
uint32 index;
}

Output

Click here to view ABI
struct CellInfo {
OutPoint outPoint;
CellOutput output;
bytes data;
}

struct CellOutput {
uint64 capacity;
Script lock;
Script[] type_;
}

Example

Click here to view example
contract GetCkbCell {
event GetCellEvent(OutPoint);
event NotGetCellEvent();

int8 ret;

function getCell(bytes32 blockHash) public returns (CellInfo memory) {
address get_cell_addr = address(0x0103);
(bool isSuccess, bytes memory res) = get_cell_addr.staticcall(
abi.encode(outPoint)
);

CellInfo memory cell;
if (isSuccess) {
cell = abi.decode(res, (CellInfo));
emit GetCellEvent(cell);
} else {
emit NotGetCellEvent();
}
return cell;
}
}

CallCkbVm

ADDRESSMINIMUM GASINPUTOUTPUT
0x0000000000000000000000000000000000000104300cell dep, argsbig-endian bytes

Call a script that runs in CKB-VM and return the execute result.

Inputs

Click here to view ABI
struct CellDep {
OutPoint outPoint;
uint32 index;
}

struct InputArgs {
bytes[] args;
}

Output

Click here to view ABI
struct Result {
int8 ret;
}

Example

Click here to view example
contract CallCkbVm {
event CallCkbVmEvent(int8);
event NotGetCellEvent();

int8 ret;

function testCallCkbVm(
bytes32 txHash,
uint32 index,
uint8 depType,
bytes[] memory input_args
) public {
OutPoint memory outPoint = OutPoint(txHash, index);
(bool isSuccess, bytes memory res) = address(0x0104).staticcall(
abi.encode(CellDep(outPoint, depType), input_args)
);

if (isSuccess) {
ret = int8(uint8(res[0]));
emit CallCkbVmEvent(ret);
} else {
emit NotGetCellEvent();
}
}

function callCkbVm() public view returns (int8) {
return ret;
}
}

CkbBlake2b

ADDRESSMINIMUM GASINPUTOUTPUT
0x000000000000000000000000000000000000010660datahash

Calculate the ckb-blake2b hash.

Inputs

Click here to view ABI
struct Input {
byte[] data;
}

Output

Click here to view ABI
struct Output {
bytes32 hash;
}

CkbMbtVerify

ADDRESSMINIMUM GASINPUTOUTPUT
0x000000000000000000000000000000000000010756000verify proof payloadbool

Verify the CKB merkle binary tree proof.

Inputs

Click here to view ABI
struct VerifyProofPayload {
uint8 verifyType;
bytes32 transactionsRoot;
bytes32 witnessesRoot;
bytes32 rawTransactionsRoot;
Proof proof;
}

struct Proof {
uint32[] indices;
bytes32[] lemmas;
bytes32[] leaves;
}

If the verify_type is 0, the leaves should be in the rawTransactionsRoot, otherwise in the witnessesRoot.

Output

Click here to view ABI
struct Output {
bool ret;
}

Example

Click here to view example
contract VerifyCMBTRoot {
event VerifyCMBTRootEvent(bool);
event NotVerifyCMBTRootEvent();

int8 ret;

function verifyCMBTRoot(VerifyProofPayload payload) public returns (bool) {
address get_cell_addr = address(0x0107);
(bool isSuccess, bytes memory res) = get_cell_addr.staticcall(
abi.encode(payload)
);

if (isSuccess) {
emit VerifyCMBTRootEvent(isSuccess);
} else {
emit NotVerifyCMBTRootEvent();
}
return isSuccess;
}
}