Precompiled Contracts

The WEMIX3.0 Blockchain provides pre-compiled contracts.

There are precompiled contracts in WEMIX smart contracts. The compiled contract provides contracts deployed in Ethereum and newly supported by WEMIX.

Recovery of ECDSA signature

The 0x01 address provides a function to recover the public key of the elliptic curve digital signature algorithm. The hash value of the transaction and the v, r, s signature value are entered, and the address is returned.

The contract address distributed on the WEMIX3.0 testnet is 0xD37d47514f46efaCa967fc191D040B3ee713110A, which can be found through testnet explorer.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.10;

contract Ecrecover {
    address addressTest = 0x12Cb274aAD8251C875c0bf6872b67d9983E53fDd;
    bytes32 msgHash = 0xc51dac836bc7841a01c4b631fa620904fc8724d7f9f1d3c420f0e02adf229d50;
    uint8 v = 0x1b;
    bytes32 r = 0x44287513919034a471a7dc2b2ed121f95984ae23b20f9637ba8dff471b6719ef;
    bytes32 s = 0x7d7dc30309a3baffbfd9342b97d0e804092c0aeb5821319aa732bc09146eafb4;


    function verify() public view returns(bool) {
        // Use ECRECOVER to verify address
        return (ecrecover(msgHash, v, r, s) == (addressTest));
    }
}

SHA256 Hash function

The 0x02 address provides an SHA-256 hash function. When the data is entered, the corresponding SHA-256 hash value is returned.

The contract address distributed on the WEMIX3.0 testnet is 0xdbec92984EE8508e3A47C150C5BDBF02B8928A72, which can be found through testnet explorer.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.10;

contract Sha256hash {
    bytes32 public expectedHash = 0x7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069;

    function calculateHash() internal pure returns (bytes32) {
        string memory word = 'Hello World!';
        bytes32 hash = sha256(bytes (word));

        return hash;        
    }

    function checkHash() public view returns(bool) {
        return (calculateHash() == expectedHash);
    }
}

RIPEMD160 Hash function

The 0x03 address provides a RIPEMD-160 hash function. When data is entered, the corresponding RIPEMD-160 hash value is returned.

The contract address distributed on the WEMIX3.0 testnet is 0x39b2CB921353097993e72e811A5FC4992b72e926, which can be found through testnet explorer.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.10;

contract Ripmd160 {
    bytes20 public expectedHash = hex'8476ee4631b9b30ac2754b0ee0c47e161d3f724c';

    function calculateHash() internal pure returns (bytes20) {
        string memory word = 'Hello World!';
        bytes20 hash = ripemd160(bytes (word));

        return hash;        
    }

    function checkHash() public view returns(bool) {
        return (calculateHash() == expectedHash);
    }
}

Data Copy function

The 0x04 address provides a data copy function. This feature is used as a more reasonable way to copy data to memory.

Currently, Solidity does not support the dataCopy function, so it must be called in-line assembly.

The contract address distributed on the WEMIX3.0 testnet is 0x709Ba0DD7055BC61B781Ddda31F5Df0018F33391, which can be found through testnet explorer.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.10;

contract Datacopy {
    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 function

The 0x05 address provides a function to raise the integer b (base) to e-square (exponential) and calculate the remainder when divided by a positive integer m (modulus).

The Solidity Compiler does not support this and must be called an inline assembly.

The contract address distributed on the WEMIX3.0 testnet is 0x370AF3a491f1D7cc08D7cc590bB2a746E612a216, which can be found through testnet explorer.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.10;

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)
        }
    }
}

Point addition on Elliptic curve

The 0x06 address provides a function that implements an addition operation for points on an elliptic curve. This operation receives two valid points(ax,ay) and(bx,by) on the elliptic curve bn256 and returns the point(ax,ay)+(bx,by) on the elliptic curve as a result.

The Solidity Compiler does not support this function and must be called an inline assembly.

The contract address distributed on the WEMIX3.0 testnet is 0x557359e169E56aAcb0d1E5FA9A7E8717967FcEbD, which can be found through testnet explorer.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.10;

contract BnAddCheck {
    bytes32[2] public checkResult;

    // Function to Verify ModExp Result
    function verify(uint ax, uint ay, uint bx, uint by) public {
        bytes32[4] memory input;
        input[0] = bytes32(ax);
        input[1] = bytes32(ay);
        input[2] = bytes32(bx);
        input[3] = bytes32(by);
        checkResult = callBn256Add(input[0], input[1], input[2], input[3]);
    }

    function callBn256Add(bytes32 ax, bytes32 ay, bytes32 bx, bytes32 by) public returns (bytes32[2] memory result) {
        bytes32[4] memory input;
        input[0] = ax;
        input[1] = ay;
        input[2] = bx;
        input[3] = by;
        assembly {
            let success := call(gas(), 0x06, 0, input, 0x80, result, 0x40)
            switch success
            case 0 {
                revert(0,0)
            }
        }
    }
}

Point multiplication on Elliptic curve

The 0x07 address provides a function that implements a multiplication operation for points on an elliptic curve expressed as scalar values. This operation takes a valid point(x,y) on the elliptic curve bn256 and returns the point scalar * (x,y) on the elliptic curve.

The Solidity Compiler does not support this function and must be called as inline assembly.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.10;

contract BnMulCheck {
    bytes32[2] public checkResult;

    // Function to Verify ModExp Result
    function verify(uint x, uint y, uint scalar) public {
        bytes32[3] memory input;
        input[0] = bytes32(x);
        input[1] = bytes32(y);
        input[2] = bytes32(scalar);
        checkResult = callBn256ScalarMul(input[0], input[1], input[2]);
    }

    function callBn256ScalarMul(bytes32 x, bytes32 y, bytes32 scalar) public returns (bytes32[2] memory result) {
        bytes32[3] memory input;
        input[0] = x;
        input[1] = y;
        input[2] = scalar;
        assembly {
            let success := call(not(0), 0x07, 0, input, 0x60, result, 0x40)
            switch success
            case 0 {
                revert(0,0)
            }
        }
    }
}

Elliptic curve pairing function for zkSNARK validation

The 0x08 address provides a function for elliptic curve peering operations to validate the zkSNARK proposed in EIP-197.

The Solidity Compiler does not support this function and must be called as inline assembly.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.10;

contract BnPairingCheck {

    ...
    function pairing(G1Point[] memory p1, G2Point[] memory p2) public returns (bool) {
        require(p1.length == p2.length);
        uint elements = p1.length;
        uint inputSize = elements * 6;
        uint[] memory input = new uint[](inputSize);
        for (uint i = 0; i < elements; i++)
        {
            input[i * 6 + 0] = p1[i].X;
            input[i * 6 + 1] = p1[i].Y;
            input[i * 6 + 2] = p2[i].X[0];
            input[i * 6 + 3] = p2[i].X[1];
            input[i * 6 + 4] = p2[i].Y[0];
            input[i * 6 + 5] = p2[i].Y[1];
        }
        uint[1] memory out;
        bool success;
        assembly {
            success := call(gas(), 0x08, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20)
            switch success
            case 0 {
                invalid()
            }
        }
        require(success);
        return out[0] != 0;
    }
    ...
}