Skip to content

Commit

Permalink
Implement 0x00 version of EIP-191 in ECDSA Library (#4063)
Browse files Browse the repository at this point in the history
  • Loading branch information
YamenMerhi committed Feb 22, 2023
1 parent adb861f commit 5323526
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/small-cars-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': patch
---

`ECDSA`: Add a function `toDataWithIntendedValidatorHash` that encodes data with version 0x00 following EIP-191.
10 changes: 10 additions & 0 deletions contracts/utils/cryptography/ECDSA.sol
Original file line number Diff line number Diff line change
Expand Up @@ -204,4 +204,14 @@ library ECDSA {
data := keccak256(ptr, 0x42)
}
}

/**
* @dev Returns an Ethereum Signed Data with intended validator, created from a
* `validator` and `data` according to the version 0 of EIP-191.
*
* See {recover}.
*/
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x00", validator, data));
}
}
16 changes: 16 additions & 0 deletions test/helpers/sign.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@ function toEthSignedMessageHash(messageHex) {
return web3.utils.sha3(Buffer.concat([prefix, messageBuffer]));
}

/**
* Create a signed data with intended validator according to the version 0 of EIP-191
* @param validatorAddress The address of the validator
* @param dataHex The data to be concatenated with the prefix and signed
*/
function toDataWithIntendedValidatorHash(validatorAddress, dataHex) {
const validatorBuffer = Buffer.from(web3.utils.hexToBytes(validatorAddress));
const dataBuffer = Buffer.from(web3.utils.hexToBytes(dataHex));
const preambleBuffer = Buffer.from('\x19');
const versionBuffer = Buffer.from('\x00');
const ethMessage = Buffer.concat([preambleBuffer, versionBuffer, validatorBuffer, dataBuffer]);

return web3.utils.sha3(ethMessage);
}

/**
* Create a signer between a contract and a signer for a voucher of method, args, and redeemer
* Note that `method` is the web3 method, not the truffle-contract method
Expand Down Expand Up @@ -43,5 +58,6 @@ const getSignFor =

module.exports = {
toEthSignedMessageHash,
toDataWithIntendedValidatorHash,
getSignFor,
};
11 changes: 10 additions & 1 deletion test/utils/cryptography/ECDSA.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const { expectRevert } = require('@openzeppelin/test-helpers');
const { toEthSignedMessageHash } = require('../../helpers/sign');
const { toEthSignedMessageHash, toDataWithIntendedValidatorHash } = require('../../helpers/sign');

const { expect } = require('chai');

Expand All @@ -8,6 +8,7 @@ const ECDSA = artifacts.require('$ECDSA');
const TEST_MESSAGE = web3.utils.sha3('OpenZeppelin');
const WRONG_MESSAGE = web3.utils.sha3('Nope');
const NON_HASH_MESSAGE = '0x' + Buffer.from('abcd').toString('hex');
const RANDOM_ADDRESS = web3.utils.toChecksumAddress(web3.utils.randomHex(20));

function to2098Format(signature) {
const long = web3.utils.hexToBytes(signature);
Expand Down Expand Up @@ -248,4 +249,12 @@ contract('ECDSA', function (accounts) {
);
});
});

context('toDataWithIntendedValidatorHash', function () {
it('returns the hash correctly', async function () {
expect(
await this.ecdsa.methods['$toDataWithIntendedValidatorHash(address,bytes)'](RANDOM_ADDRESS, NON_HASH_MESSAGE),
).to.equal(toDataWithIntendedValidatorHash(RANDOM_ADDRESS, NON_HASH_MESSAGE));
});
});
});

0 comments on commit 5323526

Please sign in to comment.