The Bifrost Network supports the standard precompiled contract installed on the Ethereum mainnet. The following is the table of addresses of the implemented precompiled contracts.
ECRECOVER
It returns the signer address of the ecdsa signature (v, r, s) if the signature is valid. It can be called directly in Solidity code.
It returns the keccak-hash value of the data. It can be called directly in Solidity code.
// contract address: 0x0000000000000000000000000000000000000002
function sha256(bytes data) returns (bytes32);
RIPEMD160
It returns the ripemd160-hash value of the data. It can be called directly in Solidity code.
// contract address: 0x0000000000000000000000000000000000000003
function ripemd160(bytes data) returns (bytes32);
Identity
Also known as datacopy, this function serves as a cost-efficient way to copy data in memory. Since the Solidity compiler does not support this function, this function must be called by assembly as follows.
// contract address: 0x0000000000000000000000000000000000000004
contract Identity{
bytes public memoryStored;
function callDatacopy(bytes memory data) public returns (bytes memory) {
bytes memory result = new bytes(data.length);
assembly {
let len := mload(data)
if iszero(call(gas(), 0x04, 0, add(data, 0x20), len, add(result,0x20), len)) {
invalid()
}
}
memoryStored = result;
return result;
}
}
Modular Exponentiation
This function calculates the remainder when an integer b(base) is raised to the e-th power(the exponent) and is divided by a positive integer m(the modulus). Since the Solidity compiler does not support this function, this function must be called by assembly as follows.
// contract address: 0x0000000000000000000000000000000000000005
contract ModularCheck {
uint public checkResult;
// Function to Verify ModExp Result
function verify( uint _base, uint _exp, uint _modulus) public {
checkResult = modExp(_base, _exp, _modulus);
}
function modExp(uint256 _b, uint256 _e, uint256 _m) public returns (uint256 result) {
assembly {
// Free memory pointer
let pointer := mload(0x40)
// Define length of base, exponent and modulus. 0x20 == 32 bytes
mstore(pointer, 0x20)
mstore(add(pointer, 0x20), 0x20)
mstore(add(pointer, 0x40), 0x20)
// Define variables base, exponent and modulus
mstore(add(pointer, 0x60), _b)
mstore(add(pointer, 0x80), _e)
mstore(add(pointer, 0xa0), _m)
// Store the result
let value := mload(0xc0)
// Call the precompiled contract 0x05 = bigModExp
if iszero(call(not(0), 0x05, 0, pointer, 0xc0, value, 0x20)) {
revert(0, 0)
}
result := mload(value)
}
}
}
BN128Add
The BN128Add precompiled contract implements a native elliptic curve point addition. It returns an elliptic curve point representing (ax, ay) + (bx, by) such that (ax, ay) and (bx, by) are valid points on the curve BN256. Since the Solidity compiler does not support this function, this function must be called by assembly as follows.
The BN128Mul precompiled contract implements a native elliptic curve multiplication with a scalar value. It returns an elliptic curve point representing scalar * (x, y) such that (x, y) is a valid curve point on the curve BN256. Since the Solidity compiler does not support this function, this function must be called by assembly as follows.
The BN128Pairing precompile implements elliptic curve paring operation to perform zkSNARK verification. For more information, check out the EIP-197 standard. Since the Solidity compiler does not support this function, this function must be called by assembly as follows.
// contract address: 0x0000000000000000000000000000000000000008
contract Precompiles {
function callBn256Pairing(bytes memory input) public returns (bytes32 result) {
// input is a serialized bytes stream of (a1, b1, a2, b2, ..., ak, bk) from (G_1 x G_2)^k
uint256 len = input.length;
require(len % 192 == 0);
assembly {
let memPtr := mload(0x40)
let success := call(gas, 0x08, 0, add(input, 0x20), len, memPtr, 0x20)
switch success
case 0 {
revert(0,0)
} default {
result := mload(memPtr)
}
}
}
}
Blake2F
This EIP will enable the BLAKE2b hash function and other higher-round 64-bit BLAKE2 variants to run cost-effectively on the EVM, allowing easier interoperability between Ethereum and Zcash or any other Equihash-based PoW coin. For more information, check out the EIP-152 standard. Since the Solidity compiler does not support this function, this function must be called by assembly as follows.