Sign Contract
DerXanRam opened this issue ยท 28 comments
Hello bro. I am trying to sign this contract on Uniswapv2 router 02
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
and i write thos code....
struct eth_abi abi;
char *fn = "swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)",
*addr = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", *hex;
char *weth="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
char *usdt="0xdAC17F958D2ee523a2206206994597C13D831ec7";
char *myaddress="0xa9d0a7dC416f586491f2fb596731598F937617b5";
size_t hexlen;
ok(eth_abi_init(&abi, ETH_ABI_ENCODE));
ok(eth_abi_call(&abi, &fn, NULL));
ok(eth_abi)
ok(eth_abi_init(&abi, 0));
ok(eth_abi_array(&abi, ETH_ABI_ENCODE));
ok(eth_abi_address(&abi,&weth));
ok(eth_abi_address(&abi,&usdt));
ok(eth_abi_array_end(&abi));
/*i try to add string "account" but i don't know how*/
ok(eth_abi_call_end(&abi));
ok(eth_abi_to_hex(&abi, &hex, &hexlen));
ok(eth_abi_free(&abi));
printf("encoded abi: %s\n", hex);
free(hex);
But as u can see the comment found in the code, i have hard time to pass string to the ABI. and also where should i add the contract address?
If u can, can u show me how i sign this contract correctly and to send to the RPC-API eth_sendRawTransaction
?plsss
Hello. If the signature of the function is swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
, it should be like this (not tested):
eth_abi_init(&abi, ETH_ABI_ENCODE)
eth_abi_call(&abi, &func_name, NULL);
eth_abi_uint256(&abi, &amount_out_min);
eth_abi_array(&abi); // open an array
eth_abi_address(&abi, &address0);
eth_abi_address(&abi, &address1);
// 2 3 4 ...
eth_abi_array_end(&abi); // close the array
eth_abi_address(&abi, &to_address);
eth_abi_uint256(&abi, &deadline);
eth_abi_call_end(&abi);
eth_abi_free(&abi);
Now, just replace variables with yours and it should work.
And, you also need to remove whitespaces and parameter names from the function signature. Replace it with this: swapExactETHForTokens(uint,address[],address,uint)
Hello. If the signature of the function is
swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
, it should be like this (not tested):eth_abi_init(&abi, ETH_ABI_ENCODE) eth_abi_call(&abi, &func_name, NULL); eth_abi_uint256(&abi, &amount_out_min); eth_abi_array(&abi); // open an array eth_abi_address(&abi, &address0); eth_abi_address(&abi, &address1); // 2 3 4 ... eth_abi_array_end(&abi); // close the array eth_abi_address(&abi, &to_address); eth_abi_uint256(&abi, &deadline); eth_abi_call_end(&abi); eth_abi_free(&abi);Now, just replace variables with yours and it should work. and can fill "account" in
eth_abi_address(&abi, &to_address);
?
ok but where do i pass the contract address?
What is that address for? Are you trying to send from that address?
Oh, I see what you mean. Take a look at this example: https://github.com/mhw0/libethc/blob/main/examples/legacy-transaction.c. Just replace the toaddr
with your contract address, and the data
field with the encoded ABI (don't forget about chainid and other things)
What is that address for? Are you trying to send from that address?
What i want to do is send the signed data by curl and sign uniswap contract... i.e like this
curl https://eth-mainnet.blastapi.io/<project-id> \
-X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":["0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"],"id":1}'
Here is the API doc
But without the Uniswap's contract address i think the network can not find the ABI or did i miss the concept? Sorry bro i am new for blockchain...
like this....
ok(eth_rlp_init(&rlp0, ETH_RLP_ENCODE));
ok(eth_rlp_array(&rlp0)); // [
ok(eth_rlp_uint8(&rlp0, &nonce)); // 0x00,
ok(eth_rlp_hex(&rlp0, &gasprice, NULL)); // 0x04a817c800,
ok(eth_rlp_hex(&rlp0, &gaslimit, NULL)); // 0x5208,
ok(eth_rlp_address(&rlp0, &toaddr)); // 0x3535353535353535353535353535353535353535,
ok(eth_rlp_hex(&rlp0, &value, NULL)); // 0x0de0b6b3a7640000,
ok(eth_rlp_hex(&rlp1, &abi_result)); // 0x, //replaced
ok(eth_rlp_uint16(&rlp0, &chainid)); // 0x7a69,
ok(eth_rlp_uint8(&rlp0, &zero)); // 0x,
ok(eth_rlp_uint8(&rlp0, &zero)); // 0x,
ok(eth_rlp_array_end(&rlp0)); // ]
ok(eth_rlp_to_bytes(&rlp0bytes, &rlp0len, &rlp0));
ok(eth_rlp_free(&rlp0));
// compute the keccak hash of the encoded rlp elements
ok(eth_keccak256(keccak, rlp0bytes, rlp0len));
free(rlp0bytes);
// sign the transaction
ok(eth_ecdsa_sign(&sign, privkey, keccak));
// calculate v
v = sign.recid + chainid * 2 + 35;
r = sign.r;
s = sign.s;
ok(eth_rlp_init(&rlp1, ETH_RLP_ENCODE));
ok(eth_rlp_array(&rlp1));
ok(eth_rlp_uint8(&rlp1, &nonce));
ok(eth_rlp_hex(&rlp1, &gasprice, NULL));
ok(eth_rlp_hex(&rlp1, &gaslimit, NULL));
ok(eth_rlp_address(&rlp1, &toaddr));
ok(eth_rlp_hex(&rlp1, &value, NULL));
ok(eth_rlp_hex(&rlp1, &abi_result)); //replaced
ok(eth_rlp_uint16(&rlp1, &v));
ok(eth_rlp_bytes(&rlp1, &r, &siglen));
ok(eth_rlp_bytes(&rlp1, &s, &siglen));
ok(eth_rlp_array_end(&rlp1));
and passing Uniswap's contract address by toaddr
. Right??
Yeah, looks right.
Ok wait...please don't close the issue....let me test it......
Hello. If the signature of the function is
swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
, it should be like this (not tested):eth_abi_init(&abi, ETH_ABI_ENCODE) eth_abi_call(&abi, &func_name, NULL); eth_abi_uint256(&abi, &amount_out_min); eth_abi_array(&abi); // open an array eth_abi_address(&abi, &address0); eth_abi_address(&abi, &address1); // 2 3 4 ... eth_abi_array_end(&abi); // close the array eth_abi_address(&abi, &to_address); eth_abi_uint256(&abi, &deadline); eth_abi_call_end(&abi); eth_abi_free(&abi);Now, just replace variables with yours and it should work. and can fill "account" in
eth_abi_address(&abi, &to_address);
?ok but where do i pass the contract address?
It is throwing error identifier "eth_abi_uint256" is undefined at this code
eth_abi_uint256(&abi, &amount_out_min);
And "too few argument" error at this code
eth_abi_array(&abi); // open an array
It is throwing error at the ABI function
"identifier "eth_abi_uint256" is undefined"
Oh, there is no function called eth_abi_uint256
. I totally forgot. Replace them with eth_abi_uint64
. Hopefully amountOutMin
and deadline
fit in uint64
And "too few argument" error at this code
eth_abi_array(&abi); // open an array
eth_abi_array
alco accepts the length of the array, So, specify the length of the path
parameter (eth_abi_array(&abi, &path_len))
path_len
does path_len
an uint64_t type which indicates number of elements in the array?
path_len
does
path_len
an intiger type which indicates number of elements in the array?
Yes, it's uint64_t
and bro what is "len" parameter indicates in this function. Very sorry for nagging u ๐ ....because it is throwing "too few arguments" error.
eth_rlp_hex(&rlp1, &abi_result));
No, it's all good. That's the length of the hex
parameter. You don't have to specify the value if your string is NUL terminated. So, just pass NULL
(eth_rlp_hex(&rlp1, &abi_result, NULL)
)
man again another error. the passed ABI hex data is
c033b18e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000014aae8060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700
which the lats 00 is hex null termination. It runs But send this message
Assertion `eth_rlp_hex(&rlp1, &abi_result,__null) >= 0' failed.
Can you please send the whole code? (Please don't leak private key)
char* SignTransaction()
{
char *abi_result="c033b18e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000014aae8060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700";
struct eth_rlp rlp0, rlp1;
struct eth_ecdsa_signature sign;
uint8_t privkey[] = {0xdf, 0x57, 0x08, 0x9f, 0xeb, 0xba, 0xcf, 0x7b,
0xa0, 0xbc, 0x22, 0x7d, 0xaf, 0xbf, 0xfa, 0x9f,
0xc0, 0x8a, 0x93, 0xfd, 0xc6, 0x8e, 0x1e, 0x42,
0x41, 0x1a, 0x14, 0xef, 0xcf, 0x23, 0x65, 0x6e};
uint8_t nonce = 0x00, zero = 0x00, keccak[32], *rlp0bytes, *r, *s;
char *gasprice = "0x04a817c800", *gaslimit = "0x5208", *value = "0x0de0b6b3a7640000";
char *toaddr = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", *txn;
uint16_t chainid = 0x1, v;
size_t rlp0len, rlp1len, siglen = 32;
ok(eth_rlp_init(&rlp0, ETH_RLP_ENCODE));
ok(eth_rlp_array(&rlp0)); // [
ok(eth_rlp_uint8(&rlp0, &nonce)); // 0x00,
ok(eth_rlp_hex(&rlp0, &gasprice, NULL)); // 0x04a817c800,
ok(eth_rlp_hex(&rlp0, &gaslimit, NULL)); // 0x5208,
ok(eth_rlp_address(&rlp0, &toaddr)); // 0x3535353535353535353535353535353535353535,
//ok(eth_rlp_hex(&rlp0, &value, NULL)); // 0x0de0b6b3a7640000,
ok(eth_rlp_hex(&rlp1, &abi_result,NULL)); //replaced
ok(eth_rlp_uint16(&rlp0, &chainid)); // 0x7a69,
//ok(eth_rlp_uint8(&rlp0, &zero)); // 0x,
//ok(eth_rlp_uint8(&rlp0, &zero)); // 0x,
ok(eth_rlp_array_end(&rlp0)); // ]
ok(eth_rlp_to_bytes(&rlp0bytes, &rlp0len, &rlp0));
ok(eth_rlp_free(&rlp0));
// compute the keccak hash of the encoded rlp elements
ok(eth_keccak256(keccak, rlp0bytes, rlp0len));
free(rlp0bytes);
// sign the transaction
ok(eth_ecdsa_sign(&sign, privkey, keccak));
// calculate v
v = sign.recid + chainid * 2 + 35;
r = sign.r;
s = sign.s;
ok(eth_rlp_init(&rlp1, ETH_RLP_ENCODE));
ok(eth_rlp_array(&rlp1));
ok(eth_rlp_uint8(&rlp1, &nonce));
ok(eth_rlp_hex(&rlp1, &gasprice, NULL));
ok(eth_rlp_hex(&rlp1, &gaslimit, NULL));
ok(eth_rlp_address(&rlp1, &toaddr));
ok(eth_rlp_hex(&rlp1, &value, NULL));
ok(eth_rlp_hex(&rlp1, &abi_result, NULL)); //replaced
ok(eth_rlp_uint16(&rlp1, &v));
ok(eth_rlp_bytes(&rlp1, &r, &siglen));
ok(eth_rlp_bytes(&rlp1, &s, &siglen));
ok(eth_rlp_array_end(&rlp1));
ok(eth_rlp_to_hex(&txn, &rlp1));
ok(eth_rlp_free(&rlp1));
return txn;
}
Thank you. Give me some time please. I'll try myself.
ok bro....i will wait ๐
here is the code with fixes:
int main(void) {
char *abi_result="c033b18e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000014aae8060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700";
struct eth_rlp rlp0, rlp1;
struct eth_ecdsa_signature sign;
uint8_t privkey[] = {0xdf, 0x57, 0x08, 0x9f, 0xeb, 0xba, 0xcf, 0x7b,
0xa0, 0xbc, 0x22, 0x7d, 0xaf, 0xbf, 0xfa, 0x9f,
0xc0, 0x8a, 0x93, 0xfd, 0xc6, 0x8e, 0x1e, 0x42,
0x41, 0x1a, 0x14, 0xef, 0xcf, 0x23, 0x65, 0x6e};
uint8_t nonce = 0x00, zero = 0x00, keccak[32], *rlp0bytes, *r, *s;
char *gasprice = "0x04a817c800", *gaslimit = "0x5208", *value = "0x0de0b6b3a7640000";
char *toaddr = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", *txn;
uint16_t chainid = 0x1, v;
size_t rlp0len, rlp1len, siglen = 32;
ok(eth_rlp_init(&rlp0, ETH_RLP_ENCODE));
ok(eth_rlp_array(&rlp0)); // [
ok(eth_rlp_uint8(&rlp0, &nonce)); // 0x00,
ok(eth_rlp_hex(&rlp0, &gasprice, NULL)); // 0x04a817c800,
ok(eth_rlp_hex(&rlp0, &gaslimit, NULL)); // 0x5208,
ok(eth_rlp_address(&rlp0, &toaddr)); // 0x3535353535353535353535353535353535353535,
ok(eth_rlp_hex(&rlp0, &value, NULL)); // 0x0de0b6b3a7640000,
// FIX1: it was rlp1, changed it to rlp0
ok(eth_rlp_hex(&rlp0, &abi_result, NULL)); //replaced
ok(eth_rlp_uint16(&rlp0, &chainid)); // 0x7a69,
// FIX2: do not comment these
ok(eth_rlp_uint8(&rlp0, &zero)); // 0x,
ok(eth_rlp_uint8(&rlp0, &zero)); // 0x,
ok(eth_rlp_array_end(&rlp0)); // ]
ok(eth_rlp_to_bytes(&rlp0bytes, &rlp0len, &rlp0));
ok(eth_rlp_free(&rlp0));
// compute the keccak hash of the encoded rlp elements
ok(eth_keccak256(keccak, rlp0bytes, rlp0len));
free(rlp0bytes);
// sign the transaction
ok(eth_ecdsa_sign(&sign, privkey, keccak));
// calculate v
v = sign.recid + chainid * 2 + 35;
r = sign.r;
s = sign.s;
ok(eth_rlp_init(&rlp1, ETH_RLP_ENCODE));
ok(eth_rlp_array(&rlp1));
ok(eth_rlp_uint8(&rlp1, &nonce));
ok(eth_rlp_hex(&rlp1, &gasprice, NULL));
ok(eth_rlp_hex(&rlp1, &gaslimit, NULL));
ok(eth_rlp_address(&rlp1, &toaddr));
ok(eth_rlp_hex(&rlp1, &value, NULL));
ok(eth_rlp_hex(&rlp1, &abi_result, NULL)); //replaced
ok(eth_rlp_uint16(&rlp1, &v));
ok(eth_rlp_bytes(&rlp1, &r, &siglen));
ok(eth_rlp_bytes(&rlp1, &s, &siglen));
ok(eth_rlp_array_end(&rlp1));
// FIX3: this actually returns the output length
ok(eth_rlp_to_hex(&txn, &rlp1) > 0);
printf("raw transaction: %s\n", txn);
ok(eth_rlp_free(&rlp1));
return 0;
}
testing....
Thanks very much. it generate the hash but the RPC-API response is not good.. But I will solve this by my self ๐
{"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"rlp: unknown tx type prefix, got: 48"}}
But i have some questions. in the corrected code what is rlp0 indicates?and what are those uncommeneted "zero"s?
But i have some questions. in the corrected code what is the difference between rlp1 and rlp0 ?
Currently, you can't replace RLP values (but it would be cool). So, you have to create two separate RLP instances for that.
and what are those uncommeneted "zero"s?
They're required values and must be included in RLP even if they're emtpy. From EIP-155: (nonce, gasprice, startgas, to, value, data, chainid, 0, 0)
Also, you have to change chain id, nonce, gas limit, gas price and value fields (value should be 0
in your case)
Please let me know if you need any help with this library :)
And, please, consider adding the code to the examples if it works. It would be very useful for others.
I will add after it worked bro. Thanks very much ๐