Skip to content

Commit

Permalink
Added test cases for standard EVM precompiles. (#3628)
Browse files Browse the repository at this point in the history
  • Loading branch information
artob committed Nov 20, 2020
1 parent b174d8c commit 6a6df0d
Show file tree
Hide file tree
Showing 5 changed files with 359 additions and 1 deletion.
137 changes: 137 additions & 0 deletions runtime/near-evm-runner/tests/build/StandardPrecompiles.abi
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
[
{
"inputs" : [],
"type" : "constructor",
"stateMutability" : "payable"
},
{
"type" : "function",
"inputs" : [],
"name" : "test_all",
"stateMutability" : "view",
"outputs" : [
{
"type" : "bool",
"internalType" : "bool",
"name" : ""
}
]
},
{
"outputs" : [
{
"type" : "bool",
"internalType" : "bool",
"name" : ""
}
],
"stateMutability" : "view",
"name" : "test_blake2f",
"inputs" : [],
"type" : "function"
},
{
"inputs" : [],
"type" : "function",
"stateMutability" : "view",
"name" : "test_ecadd",
"outputs" : [
{
"name" : "",
"internalType" : "bool",
"type" : "bool"
}
]
},
{
"inputs" : [],
"type" : "function",
"stateMutability" : "view",
"name" : "test_ecmul",
"outputs" : [
{
"internalType" : "bool",
"type" : "bool",
"name" : ""
}
]
},
{
"type" : "function",
"inputs" : [],
"name" : "test_ecpair",
"stateMutability" : "view",
"outputs" : [
{
"type" : "bool",
"internalType" : "bool",
"name" : ""
}
]
},
{
"type" : "function",
"inputs" : [],
"outputs" : [
{
"internalType" : "bool",
"type" : "bool",
"name" : ""
}
],
"stateMutability" : "pure",
"name" : "test_ecrecover"
},
{
"inputs" : [],
"type" : "function",
"outputs" : [
{
"name" : "",
"type" : "bool",
"internalType" : "bool"
}
],
"name" : "test_identity",
"stateMutability" : "view"
},
{
"outputs" : [
{
"type" : "bool",
"internalType" : "bool",
"name" : ""
}
],
"stateMutability" : "view",
"name" : "test_modexp",
"inputs" : [],
"type" : "function"
},
{
"stateMutability" : "pure",
"name" : "test_ripemd160",
"outputs" : [
{
"type" : "bool",
"internalType" : "bool",
"name" : ""
}
],
"inputs" : [],
"type" : "function"
},
{
"stateMutability" : "pure",
"name" : "test_sha256",
"outputs" : [
{
"type" : "bool",
"internalType" : "bool",
"name" : ""
}
],
"inputs" : [],
"type" : "function"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
60806040526113b5806100136000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c8063aefff86311610066578063aefff86314610143578063d06d2a3114610163578063d7d4430414610183578063da726c1b146101a3578063ff71b530146101c35761009e565b8063166f2a2f146100a35780631d82afc7146100c35780633ae57cb6146100e357806341d5e54514610103578063a7465fca14610123575b600080fd5b6100ab6101e3565b60405180821515815260200191505060405180910390f35b6100cb610303565b60405180821515815260200191505060405180910390f35b6100eb61035e565b60405180821515815260200191505060405180910390f35b61010b6103d5565b60405180821515815260200191505060405180910390f35b61012b6104b9565b60405180821515815260200191505060405180910390f35b61014b61090c565b60405180821515815260200191505060405180910390f35b61016b61097b565b60405180821515815260200191505060405180910390f35b61018b6109e2565b60405180821515815260200191505060405180910390f35b6101ab610a4c565b60405180821515815260200191505060405180910390f35b6101cb610caf565b60405180821515815260200191505060405180910390f35b60006101ed611136565b6102857f18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc960001b7f063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f3726660001b7f07c2b7f58a84bd6145f00c9c2bc0bb1a187f20ff2c92963a88019e7c6a014eed60001b7f06614e20c147e940f2d70da3f74c9a17df361706a4485c742bd6788478fa17d760001b610ce5565b90507f2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee20283970360001b816000600281106102b857fe5b60200201511480156102fd57507f301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c91560001b816001600281106102f657fe5b6020020151145b91505090565b600060606040518060400160405280602081526020017f11111111111111111111111111111111111111111111111111111111111111118152509050808051906020012061035082610d40565b805190602001201491505090565b60007fe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8556002604051806000019050602060405180830381855afa1580156103a9573d6000803e3d6000fd5b5050506040513d60208110156103be57600080fd5b810190808051906020019092919050505014905090565b60006103df611136565b61043b7f2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb760001b7f21611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb20460001b6711138ce750fa15c260001b610dc0565b90507f070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c60001b8160006002811061046e57fe5b60200201511480156104b357507f031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc60001b816001600281106104ac57fe5b6020020151145b91505090565b60006104c361090c565b610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f6572726f6e656f75732065637265636f76657220707265636f6d70696c65000081525060200191505060405180910390fd5b61053d61035e565b6105af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f6572726f6e656f75732073686132353620707265636f6d70696c65000000000081525060200191505060405180910390fd5b6105b76109e2565b610629576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f6572726f6e656f757320726970656d6431363020707265636f6d70696c65000081525060200191505060405180910390fd5b610631610303565b6106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f6572726f6e656f7573206964656e7469747920707265636f6d70696c6500000081525060200191505060405180910390fd5b6106ab61097b565b61071d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f6572726f6e656f7573206d6f6465787020707265636f6d70696c65000000000081525060200191505060405180910390fd5b6107256101e3565b610797576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f6572726f6e656f757320656361646420707265636f6d70696c6500000000000081525060200191505060405180910390fd5b61079f6103d5565b610811576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f6572726f6e656f75732065636d756c20707265636f6d70696c6500000000000081525060200191505060405180910390fd5b610819610caf565b61088b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f6572726f6e656f75732065637061697220707265636f6d70696c65000000000081525060200191505060405180910390fd5b610893610a4c565b610905576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f6572726f6e656f757320626c616b65326620707265636f6d70696c650000000081525060200191505060405180910390fd5b6001905090565b6000807f11111111111111111111111111111111111111111111111111111111111111119050606060405180608001604052806041815260200161133f6041913990506000731563915e194d8cfba1943570603f7606a31155089050610973838383610e14565b935050505090565b6000806003905060007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e905060007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f905060016109d9848484610e6e565b14935050505090565b60007f9c1185a5c5e9fc54612808977ee8f548b2258d310000000000000000000000006003604051806000019050602060405180830381855afa158015610a2d573d6000803e3d6000fd5b5050506040515160601b6bffffffffffffffffffffffff191614905090565b600080600c9050610a5b611136565b7f48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa581600060028110610a8957fe5b6020020181815250507fd182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b81600160028110610ac057fe5b602002018181525050610ad1611158565b7f616263000000000000000000000000000000000000000000000000000000000081600060048110610aff57fe5b602002018181525050600081600160048110610b1757fe5b602002018181525050600081600260048110610b2f57fe5b602002018181525050600081600360048110610b4757fe5b602002018181525050610b5861117a565b7f030000000000000000000000000000000000000000000000000000000000000081600060028110610b8657fe5b602002019077ffffffffffffffffffffffffffffffffffffffffffffffff1916908177ffffffffffffffffffffffffffffffffffffffffffffffff191681525050600081600160028110610bd657fe5b602002019077ffffffffffffffffffffffffffffffffffffffffffffffff1916908177ffffffffffffffffffffffffffffffffffffffffffffffff191681525050600060019050610c25611136565b610c328686868686610ec1565b90507fba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d181600060028110610c6257fe5b6020020151148015610ca457507f7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd400992381600160028110610c9d57fe5b6020020151145b965050505050505090565b600080610cd6604051806101a0016040528061018081526020016111bf6101809139611039565b9050600160001b811491505090565b610ced611136565b610cf5611158565b604051806080016040528087815260200186815260200185815260200184815250905060408260808360065afa8060008114610d3057610d35565b600080fd5b505050949350505050565b606080825167ffffffffffffffff81118015610d5b57600080fd5b506040519080825280601f01601f191660200182016040528015610d8e5781602001600182028036833780820191505090505b50905082518060208301826020870160045afa8060008114610daf57610db4565b600080fd5b50505080915050919050565b610dc8611136565b610dd061119c565b604051806060016040528086815260200185815260200184815250905060408260608360075afa8060008114610e0557610e0a565b600080fd5b5050509392505050565b6000806000610e238686611086565b8092508193505050818015610e6357508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b925050509392505050565b600060405160208152602080820152602060408201528460608201528360808201528260a082015260208160c08360055afa8060008114610eb25782519350610eb7565b600080fd5b5050509392505050565b610ec9611136565b610ed1611136565b60608787600060028110610ee157fe5b602002015188600160028110610ef357fe5b602002015188600060048110610f0557fe5b602002015189600160048110610f1757fe5b60200201518a600260048110610f2957fe5b60200201518b600360048110610f3b57fe5b60200201518b600060028110610f4d57fe5b60200201518c600160028110610f5f57fe5b60200201518c604051602001808b63ffffffff1660e01b81526004018a81526020018981526020018881526020018781526020018681526020018581526020018477ffffffffffffffffffffffffffffffffffffffffffffffff191681526008018377ffffffffffffffffffffffffffffffffffffffffffffffff1916815260080182151560f81b81526001019a5050505050505050505050604051602081830303815290604052905060408260d56020840160095afa806000811461102457611029565b600080fd5b5050819250505095945050505050565b60008082519050600060c0828161104c57fe5b061461105757600080fd5b604051602081836020870160085afa8060008114611078578251945061107d565b600080fd5b50505050919050565b600080604183511461109e576000809150915061112f565b60008060006020860151925060408601519150606086015160001a9050600060018883868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611117573d6000803e3d6000fd5b50505060206040510351905060018195509550505050505b9250929050565b6040518060400160405280600290602082028036833780820191505090505090565b6040518060800160405280600490602082028036833780820191505090505090565b6040518060400160405280600290602082028036833780820191505090505090565b604051806060016040528060039060208202803683378082019150509050509056fe1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daab9f0bb08640d3c1c00761cdd0121209268f6fd3816bc98b9e6f3cc77bf82b69812ac7a61788a0fdc0e19180f14c945a8e1088a27d92a74dce81c0981fb6447441ba26469706673582212203acf67adc69694b9cae057a502d5c1741f3f0e71a7bd73034e88327c199996da64736f6c63430007030033
180 changes: 180 additions & 0 deletions runtime/near-evm-runner/tests/contracts/StandardPrecompiles.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.7.0;

//import "hardhat/console.sol";

contract StandardPrecompiles {
constructor() payable {
//console.log("Deploying StandardPrecompiles");
}

function test_all() public view returns(bool) {
require(test_ecrecover(), "erroneous ecrecover precompile");
require(test_sha256(), "erroneous sha256 precompile");
require(test_ripemd160(), "erroneous ripemd160 precompile");
require(test_identity(), "erroneous identity precompile");
require(test_modexp(), "erroneous modexp precompile");
require(test_ecadd(), "erroneous ecadd precompile");
require(test_ecmul(), "erroneous ecmul precompile");
require(test_ecpair(), "erroneous ecpair precompile");
require(test_blake2f(), "erroneous blake2f precompile");
return true;
}

// See: https://docs.soliditylang.org/en/develop/units-and-global-variables.html#mathematical-and-cryptographic-functions
// See: https://etherscan.io/address/0x0000000000000000000000000000000000000001
function test_ecrecover() public pure returns(bool) {
bytes32 hash = hex"1111111111111111111111111111111111111111111111111111111111111111";
bytes memory sig = hex"b9f0bb08640d3c1c00761cdd0121209268f6fd3816bc98b9e6f3cc77bf82b69812ac7a61788a0fdc0e19180f14c945a8e1088a27d92a74dce81c0981fb6447441b";
address signer = 0x1563915e194D8CfBA1943570603F7606A3115508;
return ecverify(hash, sig, signer);
}

// See: https://docs.soliditylang.org/en/develop/units-and-global-variables.html#mathematical-and-cryptographic-functions
// See: https://etherscan.io/address/0x0000000000000000000000000000000000000002
function test_sha256() public pure returns(bool) {
return sha256("") == hex"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
}

// See: https://docs.soliditylang.org/en/develop/units-and-global-variables.html#mathematical-and-cryptographic-functions
// See: https://etherscan.io/address/0x0000000000000000000000000000000000000003
function test_ripemd160() public pure returns(bool) {
return ripemd160("") == hex"9c1185a5c5e9fc54612808977ee8f548b2258d31";
}

// See: https://etherscan.io/address/0x0000000000000000000000000000000000000004
function test_identity() public view returns(bool) {
bytes memory data = hex"1111111111111111111111111111111111111111111111111111111111111111";
return keccak256(datacopy(data)) == keccak256(data);
}

// See: https://eips.ethereum.org/EIPS/eip-198
// See: https://etherscan.io/address/0x0000000000000000000000000000000000000005
function test_modexp() public view returns(bool) {
uint256 base = 3;
uint256 exponent = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e;
uint256 modulus = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f;
return modexp(base, exponent, modulus) == 1;
}

// See: https://eips.ethereum.org/EIPS/eip-196
// See: https://etherscan.io/address/0x0000000000000000000000000000000000000006
function test_ecadd() public pure returns(bool) {
return true; // TODO
}

// See: https://eips.ethereum.org/EIPS/eip-196
// See: https://etherscan.io/address/0x0000000000000000000000000000000000000007
function test_ecmul() public pure returns(bool) {
return true; // TODO
}

// See: https://eips.ethereum.org/EIPS/eip-197
// See: https://etherscan.io/address/0x0000000000000000000000000000000000000008
function test_ecpair() public pure returns(bool) {
return true; // TODO
}

// See: https://eips.ethereum.org/EIPS/eip-152
// See: https://etherscan.io/address/0x0000000000000000000000000000000000000009
function test_blake2f() public view returns(bool) {
uint32 rounds = 12;
bytes32[2] memory h;
h[0] = hex"48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5";
h[1] = hex"d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b";
bytes32[4] memory m;
m[0] = hex"6162630000000000000000000000000000000000000000000000000000000000";
m[1] = hex"0000000000000000000000000000000000000000000000000000000000000000";
m[2] = hex"0000000000000000000000000000000000000000000000000000000000000000";
m[3] = hex"0000000000000000000000000000000000000000000000000000000000000000";
bytes8[2] memory t;
t[0] = hex"03000000";
t[1] = hex"00000000";
bool f = true;
bytes32[2] memory result = blake2f(rounds, h, m, t, f);
return result[0] == hex"ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1" && result[1] == hex"7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923";
}

function ecverify(bytes32 hash, bytes memory sig, address signer) private pure returns (bool) {
bool ret;
address addr;
(ret, addr) = ecrecovery(hash, sig);
return ret && addr == signer;
}

function ecrecovery(bytes32 hash, bytes memory sig) private pure returns (bool, address) {
if (sig.length != 65)
return (false, address(0));

bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := byte(0, mload(add(sig, 96)))
}

address addr = ecrecover(hash, v, r, s);
return (true, addr);
}

function datacopy(bytes memory input) private view returns (bytes memory) {
bytes memory output = new bytes(input.length);
assembly {
let len := mload(input)
if iszero(staticcall(gas(), 0x04, add(input, 32), len, add(output, 32), len)) {
revert(0, 0)
}
}
return output;
}

function modexp(uint256 base, uint256 exponent, uint256 modulus) private view returns (uint256) {
bytes32 ret;
assembly {
let ptr := mload(0x40)
mstore(ptr, 32)
mstore(add(ptr, 0x20), 32)
mstore(add(ptr, 0x40), 32)
mstore(add(ptr, 0x60), base)
mstore(add(ptr, 0x80), exponent)
mstore(add(ptr, 0xA0), modulus)
let ok := staticcall(gas(), 0x05, ptr, 0xC0, ptr, 0x20)
switch ok
case 0 {
revert(0, 0)
}
default {
ret := mload(ptr)
}
}
return uint256(ret);
}

function ecadd(uint256 ax, uint256 ay, uint256 bx, uint256 by) private view returns (bytes32[2] memory output) {
bytes32[4] memory input;
input[0] = bytes32(ax);
input[1] = bytes32(ay);
input[2] = bytes32(bx);
input[3] = bytes32(by);
assembly {
let ok := staticcall(gas(), 0x06, input, 0x80, output, 0x40)
switch ok
case 0 {
revert(0, 0)
}
}
}

function blake2f(uint32 rounds, bytes32[2] memory h, bytes32[4] memory m, bytes8[2] memory t, bool f) private view returns (bytes32[2] memory) {
bytes32[2] memory output;
bytes memory args = abi.encodePacked(rounds, h[0], h[1], m[0], m[1], m[2], m[3], t[0], t[1], f);
assembly {
if iszero(staticcall(gas(), 0x09, add(args, 32), 0xd5, output, 0x40)) {
revert(0, 0)
}
}
return output;
}
}
Loading

0 comments on commit 6a6df0d

Please sign in to comment.