If I do remember correctly, it’s a contract built‑in in the Ethereum Virtual machine, isn’t it?

if yes, what’s the address to call for it?


The ecrecover address is: 0x01

Without assembly you can call the ecrecover function like that:

function recoverEC_Method1 (bytes32 _hash, bytes32 _r, bytes32 _s, uint8 _v) public pure returns (address) {
    bytes memory prefix = "\x19Ethereum Signed Message:\n32";
    bytes32 prefixedHash = keccak256(abi.encodePacked(prefix, _hash));
    return ecrecover(prefixedHash, _v, _r, _s);

With assembly (one possible alternative):

function recoverEC_Method2 (bytes32 _hash, bytes32 _r, bytes32 _s, uint8 _v) public view returns (address) {

    bytes memory prefix = "\x19Ethereum Signed Message:\n32";
    bytes32 prefixedHash = keccak256(abi.encodePacked(prefix, _hash));

    assembly {
        let pointer := mload(0x40)

        mstore(pointer, prefixedHash)
        mstore(add(pointer, 0x20), _v)
        mstore(add(pointer, 0x40), _r)
        mstore(add(pointer, 0x60), _s)

        if iszero(staticcall(not(0), 0x01, pointer, 0x80, pointer, 0x20)) {
            revert(0, 0)

        let size := returndatasize
        returndatacopy(pointer, 0, size)


bytes32 _hash = 0x852daa74cc3c31fe64542bb9b8764cfb91cc30f9acf9389071ffb44a9eefde46;
bytes32 _r = 0xb814eaab5953337fed2cf504a5b887cddd65a54b7429d7b191ff1331ca0726b1;
bytes32 _s = 0x264de2660d307112075c15f08ba9c25c9a0cc6f8119aff3e7efb0a942773abb0;
uint8 _v = 0x1b;
address = 0xa6fb229e9b0a4e4ef52ea6991adcfc59207c7711

For more information about the prefix, read the following issue.

TL;DR; Geth prepends the string \x19Ethereum Signed Message:\n<length of message> to all data before signing it (https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign). If you want to verify such a signature from Solidity, you'll have to prepend the same string in solidity before doing the ecrecovery.

  • And if there’s not enough gas for having ecrecover working with the current message, what does happens next? Sep 30 '19 at 11:18
  • A revert is produced. You can test it changing not(0) to 1000 for example.
    – alberto
    Sep 30 '19 at 11:26
  • Yes, a revert/throw is produced, but in the calling contract or inside the ecrecover() built‑in contract? Sep 30 '19 at 11:28
  • The revert is produced because of not enough gas. The staticcall returns 0 (fail), instead of 1.
    – alberto
    Sep 30 '19 at 12:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.