Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for computing function 4-byte selectors from ABI #357

Closed
LogvinovLeon opened this issue Nov 28, 2018 · 6 comments
Closed

Add support for computing function 4-byte selectors from ABI #357

LogvinovLeon opened this issue Nov 28, 2018 · 6 comments
Labels
enhancement New feature or improvement.

Comments

@LogvinovLeon
Copy link

It would be nice to be able to compute 4-byte selectors from ABI. I'm talking about those: https://www.4byte.directory/signatures/
Smth like:

ethers.utils.getMethodSelector('callDeposit(address,address,uint256)') // `0xac9f2b7b`
ethers.utils.getMethodSelector('CaptureTheFlag(string flagName)') // `0x95907291 `

Should be pretty simple as it just requires removing the parameter names and hashing the thing taking the first 4 bytes.

@LogvinovLeon
Copy link
Author

I can create a PR for it if you agree it's useful and we agree on the interface.

@ricmoo
Copy link
Member

ricmoo commented Nov 29, 2018

This may make sense, but generally if you need the sighash, you often need most of the other parts of the interface as well, which would just be thrown away...

let descr = new utils.Interface([ "function transfer(address, uint)" ]);

// The signhash
console.log("sighash", descr.functions..transfer.sighash);
// "0xa9059cbb"

// But also, you would often need/want to encode parameters
console.log(descr.functions.transfer.encode(["0x0123456789012345678901234567890123456789", 1234]));
// "0xa9059cbb000000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000004d2"

// And the ability to parse the response
console.log(descr.functions.transfer.decode(callResponse));

It may make sense to add as a static method on the Interface, but let me think about it.

@ricmoo ricmoo added the discussion Questions, feedback and general information. label Nov 29, 2018
@LogvinovLeon
Copy link
Author

Ok, I agree. This is redundant. One other question. Can I also decode parameters using the Interface? I haven't found that feature. I want to decode the call data, not the return data.

@ricmoo
Copy link
Member

ricmoo commented Dec 4, 2018

const abi = [
    "function transfer(address to, uint256 amount)"
];

const iface = new ethers.utils.Interface(abi);
const transferFunc = iface.functions.transfer;

// Encoding
let address = "0x0123456789012345678901234567890123456789";
let amount = 1000;
let calldata = transferFunc.encode([address, amount]);
console.log(calldata);
// "0xa9059cbb000000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000003e8"

// Decoding
console.log(iface.parseTransaction({ data: calldata, value: "0x0" }));
// _TransactionDescription {
//  args:
//   [ '0x0123456789012345678901234567890123456789',
//     BigNumber { _hex: '0x03e8' } ],
//  decode: [Function],
//  name: 'transfer(address,uint256)',
//  signature: 'transfer(address,uint256)',
//  sighash: '0xa9059cbb',
//  value: BigNumber { _hex: '0x0' } }

(note this example just pointed out a bug; for now, value is required; I'll remove this requirement shortly)

@ricmoo ricmoo added enhancement New feature or improvement. on-deck This Enhancement or Bug is currently being worked on. and removed discussion Questions, feedback and general information. labels Dec 4, 2018
@ricmoo
Copy link
Member

ricmoo commented Dec 4, 2018

This should now work with value omitted. Let me know if you have any issues.

Thanks! :)

@ricmoo ricmoo closed this as completed Dec 4, 2018
@ricmoo ricmoo removed the on-deck This Enhancement or Bug is currently being worked on. label Dec 4, 2018
@wellitongervickas
Copy link

Get first the fragment of abi function

const fragment = contract.interface.getFunction(method)

Then, get bytes4 signature of function

const selectorHash = contract.interface.getSighash(fragment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or improvement.
Projects
None yet
Development

No branches or pull requests

3 participants