0

I'm in need of help using Lib ECDSA. What am I trying to do? I'm trying to get a subscription and check my Smart Contract if everything is ok.

Below I'm putting my files that I have so far.

When I run the tests it is entering the "else" condition, shouldn't it enter the IF condition? or am i using recover with the wrong parameters?

Would they be able to help me?

pragma solidity >=0.4.22 <0.9.0;

import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "./TokenERC20.sol";

contract InstanceCoin{

    address contractInstance;

    constructor(address _contract){
        contractInstance = _contract;
    }

    function reedemToken(uint _amount, bytes32 _hash, bytes memory _signature) public {
        // TokenERC20 token = TokenERC20(contractInstance);
        if(ECDSA.recover(_hash, _signature) == msg.sender)
            revert("is correct");
        else 
            revert("is not correct"); //revert just test
    }
}

My file.js

const InstanceCoin = artifacts.require('coins/InstanceCoin');
const EthCrypto = require("eth-crypto");

const signerIdentity = EthCrypto.createIdentity();
const message = EthCrypto.hash.keccak256 ([ 
    {type: "uint256", value: "500"},     
  ]);
const signature = EthCrypto.sign(signerIdentity.privateKey, message);

console.log(`message: ${message}`);
console.log(`signature: ${signature}`);
console.log(`signer public key: ${signerIdentity.address}`);

contract("InstanceCoin", (accounts) => {    
    let [alice, bob, cain, dan] = accounts;
    let contractInstance;
    beforeEach(async () => {        
        contractInstance = await InstanceCoin.deployed();              
    });
    describe("deploys", async () => {
        it("just only test", async () => {
            await contractInstance.reedemToken(10, message, signature, {from: alice});
        });
    });
})

Output test:

     Error: Returned error: VM Exception while processing transaction: revert is not correct -- Reason given: is not correct.     
2
  • You are generating a signature matching the address of signerIdentity, But then you send that same signature using {from: alice}. It must fail as alice's address will not match a recover from signature.
    – hroussille
    Nov 3, 2021 at 17:11
  • @Hroussile but do i need to generate a private subscription for alice then? it is not?
    – Crazy
    Nov 3, 2021 at 18:15

1 Answer 1

0

I modified your code a little:

Simple contract validating the the signature matches the msg.sender, if not : revert.

pragma solidity >=0.8.0 <0.9.0;

import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

contract Recover{

    function reedemToken(uint _amount, bytes32 _hash, bytes memory _signature) public view {
        // TokenERC20 token = TokenERC20(contractInstance);
        if(ECDSA.recover(_hash, _signature) != msg.sender) {
            revert("Signature does not match message sender");
        } 
    }
}

And a simple test file :

const Recover = artifacts.require('Recover');
const EthCrypto = require("eth-crypto");

// Taken from ganache-cli : private key of the first account : accounts[0]
// Change it to match your private key
const privateKey = "0xce15d9e0330b9570ac1f5b9240717ad2c175f077632a699802767314f15a9205";


const publicKey = EthCrypto.publicKeyByPrivateKey(privateKey);
const address = EthCrypto.publicKey.toAddress(publicKey);

const message = EthCrypto.hash.keccak256 ([{type: "uint256", value: "500"},]);
const signature = EthCrypto.sign(privateKey, message);

let contractInstance;

console.log(`message: ${message}`);
console.log(`signature: ${signature}`);
console.log(`signer public key: ${publicKey}`);
console.log(`signer address ${address}`);

contract("Recover", (accounts) => {
    
    beforeEach(async () => {        
        contractInstance = await Recover.deployed();              
    });

    describe("Validate ECDSA contract behavior", async () => {
        it("Verifies that the message is signed by accounts[0]", async () => {
            await contractInstance.reedemToken(10, message, signature, {from: accounts[0]});
        });

        it("Verifies that the message was NOT signed by accounts[0]", async () => {
            await contractInstance.reedemToken(10, message, signature, {from: accounts[1]});
        });
    });
})

As you can see if you run the tests :

test 1 succeed because account[0] private key was used to sign the message. And account[0] is the message sender, so the address recovery matches msg.sender.

test 2 fails because msg.sender is accounts[1]. Which is definitely not a match with account[0] recovered from the message and signature on the contract side.

To generate a signature for Alice, you need to sign the message with Alice's private key. There is no other way. Only the private key holder can sign a message that authenticates him/her.

Think of the Recovery operation as validating that the person who sent you this message has the address X and holds the private key associated with it.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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