diff --git a/iguana/exchanges/LP_etomic.c b/iguana/exchanges/LP_etomic.c index a52638ab7..4a916cb24 100644 --- a/iguana/exchanges/LP_etomic.c +++ b/iguana/exchanges/LP_etomic.c @@ -25,6 +25,30 @@ #include "etomicswap/etomiccurl.h" #include +int32_t LP_etomic_wait_for_confirmation(char *txId) +{ + EthTxReceipt receipt; + EthTxData txData; + do { + sleep(15); + printf("waiting for ETH txId to be confirmed: %s\n", txId); + receipt = getEthTxReceipt(txId); + if (receipt.confirmations < 1) { + txData = getEthTxData(txId); + if (txData.exists == 0) { + return(-1); + } + } + } while (receipt.confirmations < 1); + + if (strcmp(receipt.status, "0x1") != 0) { + printf("ETH txid %s receipt status failed\n", txId); + return(-1); + } + + return(receipt.confirmations); +} + char *LP_etomicalice_send_payment(struct basilisk_swap *swap) { AliceSendsEthPaymentInput input; AliceSendsErc20PaymentInput input20; BasicTxData txData; @@ -60,10 +84,71 @@ char *LP_etomicalice_send_payment(struct basilisk_swap *swap) strcpy(txData.to, ETOMIC_ALICECONTRACT); strcpy(txData.amount, "0"); uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); + + uint64_t allowance = getErc20Allowance(swap->I.etomicsrc, ETOMIC_ALICECONTRACT, swap->I.alicetomic); + if (allowance < swap->I.alicesatoshis) { + printf("Alice token allowance is too low, setting new allowance\n"); + ApproveErc20Input approveErc20Input; + strcpy(approveErc20Input.tokenAddress, swap->I.alicetomic); + strcpy(approveErc20Input.owner, swap->I.etomicsrc); + strcpy(approveErc20Input.spender, ETOMIC_ALICECONTRACT); + + // hard code for now + strcpy(approveErc20Input.amount, "20000000000000000000"); + strcpy(approveErc20Input.secret, txData.secretKey); + + char *allowTxId = approveErc20(approveErc20Input); + LP_etomic_wait_for_confirmation(allowTxId); + free(allowTxId); + } + return(aliceSendsErc20Payment(input20,txData)); } } +uint8_t LP_etomic_verify_alice_payment(struct basilisk_swap *swap, char *txId) +{ + EthTxData data = getEthTxData(txId); + if (data.exists == 0 || strcmp(data.to, ETOMIC_ALICECONTRACT) != 0 || strcmp(data.from, swap->I.etomicdest) != 0) { + return 0; + } + AliceSendsEthPaymentInput input; AliceSendsErc20PaymentInput input20; BasicTxData txData; + + // set input and txData fields from the swap data structure + memset(&txData,0,sizeof(txData)); + if ( strcmp(swap->I.alicestr,"ETH") == 0 ) + { + memset(&input,0,sizeof(input)); + strcpy(input.bobAddress, swap->I.etomicsrc); + uint8arrayToHex(input.bobHash, swap->I.secretBn, 20); + uint8arrayToHex(input.aliceHash, swap->I.secretAm, 20); + uint8arrayToHex(input.dealId, swap->alicepayment.I.actualtxid.bytes, 32); + + strcpy(txData.from, swap->I.etomicdest); + strcpy(txData.to, ETOMIC_ALICECONTRACT); + satoshisToWei(txData.amount, swap->I.alicesatoshis); + uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); + + return(verifyAliceEthPaymentData(input, data.input)); + } + else + { + memset(&input20,0,sizeof(input20)); + strcpy(input20.bobAddress, swap->I.etomicdest); + uint8arrayToHex(input20.bobHash, swap->I.secretBn, 20); + uint8arrayToHex(input20.aliceHash, swap->I.secretAm, 20); + uint8arrayToHex(input20.dealId, swap->alicepayment.utxotxid.bytes, 32); + strcpy(input20.tokenAddress, swap->I.alicetomic); + satoshisToWei(input20.amount, swap->I.alicesatoshis); + + strcpy(txData.from, swap->I.etomicsrc); + strcpy(txData.to, ETOMIC_ALICECONTRACT); + strcpy(txData.amount, "0"); + uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); + return(verifyAliceErc20PaymentData(input20, data.input)); + } +} + char *LP_etomicalice_reclaims_payment(struct LP_swap_remember *swap) { AliceReclaimsAlicePaymentInput input; @@ -166,10 +251,65 @@ char *LP_etomicbob_sends_deposit(struct basilisk_swap *swap) strcpy(txData.to, ETOMIC_BOBCONTRACT); strcpy(txData.amount, "0"); uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); + + uint64_t allowance = getErc20Allowance(swap->I.etomicsrc, ETOMIC_BOBCONTRACT, swap->I.bobtomic); + if (allowance < swap->bobdeposit.I.amount) { + printf("Bob token allowance is too low, setting new allowance\n"); + ApproveErc20Input approveErc20Input; + strcpy(approveErc20Input.tokenAddress, swap->I.bobtomic); + strcpy(approveErc20Input.owner, swap->I.etomicsrc); + strcpy(approveErc20Input.spender, ETOMIC_BOBCONTRACT); + + // hard code for now + strcpy(approveErc20Input.amount, "20000000000000000000"); + strcpy(approveErc20Input.secret, txData.secretKey); + + char *allowTxId = approveErc20(approveErc20Input); + LP_etomic_wait_for_confirmation(allowTxId); + free(allowTxId); + } + return bobSendsErc20Deposit(input20, txData); } } +uint8_t LP_etomic_verify_bob_deposit(struct basilisk_swap *swap, char *txId) +{ + EthTxData data = getEthTxData(txId); + if (data.exists == 0 || strcmp(data.to, ETOMIC_BOBCONTRACT) != 0 || strcmp(data.from, swap->I.etomicsrc) != 0) { + return 0; + } + BobSendsEthDepositInput input; + BobSendsErc20DepositInput input20; + BasicTxData txData; + memset(&txData,0,sizeof(txData)); + memset(&input,0,sizeof(input)); + memset(&input20,0,sizeof(input20)); + if ( strcmp(swap->I.bobstr,"ETH") == 0 ) { + uint8arrayToHex(input.depositId, swap->bobdeposit.I.actualtxid.bytes, 32); + strcpy(input.aliceAddress, swap->I.etomicdest); + uint8arrayToHex(input.bobHash, swap->I.secretBn, 20); + + strcpy(txData.from, swap->I.etomicsrc); + strcpy(txData.to, ETOMIC_BOBCONTRACT); + satoshisToWei(txData.amount, swap->bobdeposit.I.amount); + uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); + return verifyBobEthDepositData(input, data.input); + } else { + uint8arrayToHex(input20.depositId, swap->bobdeposit.I.actualtxid.bytes, 32); + strcpy(input20.aliceAddress, swap->I.etomicdest); + uint8arrayToHex(input20.bobHash, swap->I.secretBn, 20); + satoshisToWei(input20.amount, swap->bobdeposit.I.amount); + strcpy(input20.tokenAddress, swap->I.bobtomic); + + strcpy(txData.from, swap->I.etomicsrc); + strcpy(txData.to, ETOMIC_BOBCONTRACT); + strcpy(txData.amount, "0"); + uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); + return verifyBobErc20DepositData(input20, data.input); + } +} + char *LP_etomicbob_refunds_deposit(struct LP_swap_remember *swap) { BobRefundsDepositInput input; @@ -238,10 +378,66 @@ char *LP_etomicbob_sends_payment(struct basilisk_swap *swap) strcpy(txData.to, ETOMIC_BOBCONTRACT); strcpy(txData.amount, "0"); uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); + + uint64_t allowance = getErc20Allowance(swap->I.etomicsrc, ETOMIC_BOBCONTRACT, swap->I.bobtomic); + if (allowance < swap->bobpayment.I.amount) { + printf("Bob token allowance is too low, setting new allowance\n"); + ApproveErc20Input approveErc20Input; + strcpy(approveErc20Input.tokenAddress, swap->I.bobtomic); + strcpy(approveErc20Input.owner, swap->I.etomicsrc); + strcpy(approveErc20Input.spender, ETOMIC_BOBCONTRACT); + + // hard code for now + strcpy(approveErc20Input.amount, "20000000000000000000"); + strcpy(approveErc20Input.secret, txData.secretKey); + + char *allowTxId = approveErc20(approveErc20Input); + LP_etomic_wait_for_confirmation(allowTxId); + free(allowTxId); + } + return bobSendsErc20Payment(input20, txData); } } +uint8_t LP_etomic_verify_bob_payment(struct basilisk_swap *swap, char *txId) +{ + EthTxData data = getEthTxData(txId); + if (data.exists == 0 || strcmp(data.to, ETOMIC_BOBCONTRACT) != 0 || strcmp(data.from, swap->I.etomicsrc) != 0) { + return 0; + } + BobSendsEthPaymentInput input; + BobSendsErc20PaymentInput input20; + BasicTxData txData; + memset(&txData,0,sizeof(txData)); + memset(&input,0,sizeof(input)); + memset(&input20,0,sizeof(input20)); + + if ( strcmp(swap->I.bobstr,"ETH") == 0 ) { + uint8arrayToHex(input.paymentId, swap->bobpayment.I.actualtxid.bytes, 32); + strcpy(input.aliceAddress, swap->I.etomicdest); + uint8arrayToHex(input.aliceHash, swap->I.secretAm, 20); + + strcpy(txData.from, swap->I.etomicsrc); + strcpy(txData.to, ETOMIC_BOBCONTRACT); + satoshisToWei(txData.amount, swap->bobpayment.I.amount); + uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); + return verifyBobEthPaymentData(input, data.input); + } else { + uint8arrayToHex(input20.paymentId, swap->bobpayment.I.actualtxid.bytes, 32); + strcpy(input20.aliceAddress, swap->I.etomicdest); + uint8arrayToHex(input20.aliceHash, swap->I.secretAm, 20); + satoshisToWei(input20.amount, swap->bobpayment.I.amount); + strcpy(input20.tokenAddress, swap->I.bobtomic); + + strcpy(txData.from, swap->I.etomicsrc); + strcpy(txData.to, ETOMIC_BOBCONTRACT); + strcpy(txData.amount, "0"); + uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); + return verifyBobErc20PaymentData(input20, data.input); + } +} + char *LP_etomicbob_reclaims_payment(struct LP_swap_remember *swap) { BobReclaimsBobPaymentInput input; @@ -405,26 +601,10 @@ int32_t LP_etomic_pub2addr(char *coinaddr,uint8_t pub64[64]) return(-1); } -int32_t LP_etomic_wait_for_confirmation(char *txId) +uint8_t LP_etomic_is_empty_tx_id(char *txId) { - EthTxReceipt receipt; - EthTxData txData; - do { - sleep(15); - printf("waiting for ETH txId to be confirmed: %s\n", txId); - receipt = getEthTxReceipt(txId); - if (receipt.confirmations < 1) { - txData = getEthTxData(txId); - if (txData.exists == 0) { - return(-1); - } - } - } while (receipt.confirmations < 1); - - if (strcmp(receipt.status, "0x1") != 0) { - printf("ETH txid %s receipt status failed\n", txId); - return(-1); + if (strcmp(txId, EMPTY_ETH_TX_ID) == 0) { + return 1; } - - return(receipt.confirmations); + return 0; } diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index 0d29b5b5e..78ba77167 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -2206,7 +2206,7 @@ int32_t LP_verify_bobdeposit(struct basilisk_swap *swap,uint8_t *data,int32_t da //basilisk_txlog(swap,&swap->aliceclaim,swap->I.putduration+swap->I.callduration); #ifndef NOTETOMIC if (swap->bobdeposit.I.ethTxid[0] != 0) { - if (LP_etomic_wait_for_confirmation(swap->bobdeposit.I.ethTxid) < 0) { + if (LP_etomic_wait_for_confirmation(swap->bobdeposit.I.ethTxid) < 0 || LP_etomic_verify_bob_deposit(swap, swap->bobdeposit.I.ethTxid) == 0) { return(-1); } } @@ -2235,8 +2235,8 @@ int32_t LP_verify_alicepayment(struct basilisk_swap *swap,uint8_t *data,int32_t swap->aliceunconf = 1; basilisk_dontforget_update(swap,&swap->alicepayment); #ifndef NOTETOMIC - if (swap->alicepayment.I.ethTxid[0] != 0) { - if (LP_etomic_wait_for_confirmation(swap->alicepayment.I.ethTxid) < 0) { + if (swap->alicepayment.I.ethTxid[0] != 0 && LP_etomic_is_empty_tx_id(swap->alicepayment.I.ethTxid) == 0) { + if (LP_etomic_wait_for_confirmation(swap->alicepayment.I.ethTxid) < 0 || LP_etomic_verify_alice_payment(swap, swap->alicepayment.I.ethTxid) == 0) { return(-1); } } @@ -2294,9 +2294,9 @@ int32_t LP_verify_bobpayment(struct basilisk_swap *swap,uint8_t *data,int32_t da bitcoin_address(coin->symbol,swap->alicespend.I.destaddr,coin->taddr,coin->pubtype,swap->persistent_pubkey33,33); //char str[65],str2[65]; printf("bobpaid privAm.(%s) myprivs[0].(%s)\n",bits256_str(str,swap->I.privAm),bits256_str(str2,swap->I.myprivs[0])); #ifndef NOTETOMIC - if (swap->bobpayment.I.ethTxid[0] != 0) { - if (LP_etomic_wait_for_confirmation(swap->bobpayment.I.ethTxid) < 0) { - return (-1); + if (swap->bobpayment.I.ethTxid[0] != 0 && LP_etomic_is_empty_tx_id(swap->bobpayment.I.ethTxid) == 0) { + if (LP_etomic_wait_for_confirmation(swap->bobpayment.I.ethTxid) < 0 || LP_etomic_verify_bob_payment(swap, swap->bobpayment.I.ethTxid) == 0) { + return(-1); } } #endif diff --git a/iguana/exchanges/etomicswap/bob.c b/iguana/exchanges/etomicswap/bob.c index 7239bb324..a17898361 100644 --- a/iguana/exchanges/etomicswap/bob.c +++ b/iguana/exchanges/etomicswap/bob.c @@ -220,12 +220,14 @@ int main(int argc, char** argv) } break; case BOB_APPROVES_ERC20: - result = approveErc20( - "10000000000000000000", - "0xA7EF3f65714AE266414C9E58bB4bAa4E6FB82B41", - getenv("BOB_PK") - - ); + printf("approving erc20\n"); + ApproveErc20Input input8; + strcpy(input8.amount, "20000000000000000000"); + strcpy(input8.spender, bobContractAddress); + strcpy(input8.owner, bobAddress); + strcpy(input8.tokenAddress, tokenAddress); + strcpy(input8.secret, getenv("BOB_PK")); + result = approveErc20(input8); if (result != NULL) { printf("%s\n", result); free(result); @@ -270,5 +272,11 @@ int main(int argc, char** argv) satoshisToWei(weiBuffer, satoshis); printf("wei: %s\n", weiBuffer); + uint8_t decimals = getErc20Decimals(tokenAddress); + printf("decimals: %d\n", decimals); + + uint64_t tokenAllowance = getErc20Allowance(bobAddress, bobContractAddress, tokenAddress); + printf("allowance: %" PRIu64 "\n", tokenAllowance); + return 0; } diff --git a/iguana/exchanges/etomicswap/etomiclib.cpp b/iguana/exchanges/etomicswap/etomiclib.cpp index 38efb0a08..03e8b79d8 100644 --- a/iguana/exchanges/etomicswap/etomiclib.cpp +++ b/iguana/exchanges/etomicswap/etomiclib.cpp @@ -12,7 +12,7 @@ using namespace dev; using namespace dev::eth; -char* stringStreamToChar(std::stringstream& ss) +char *stringStreamToChar(std::stringstream& ss) { const std::string tmp = ss.str(); auto result = (char*)malloc(strlen(tmp.c_str()) + 1); @@ -32,7 +32,7 @@ TransactionSkeleton txDataToSkeleton(BasicTxData txData) return tx; } -char* signTx(TransactionSkeleton& tx, char* secret) +char *signTx(TransactionSkeleton& tx, char* secret) { Secret& secretKey = *(new Secret(secret)); auto baseTx = new TransactionBase(tx, secretKey); @@ -43,30 +43,29 @@ char* signTx(TransactionSkeleton& tx, char* secret) return stringStreamToChar(ss); } -char* approveErc20(char* amount, char* from, char* secret) +char *approveErc20(ApproveErc20Input input) { TransactionSkeleton tx; - tx.from = jsToAddress(from); - tx.to = jsToAddress("0xc0eb7AeD740E1796992A08962c15661bDEB58003"); - tx.value = 0; // exp10<18>(); + tx.from = jsToAddress(input.owner); + tx.to = jsToAddress(input.tokenAddress); + tx.value = 0; tx.gas = 300000; tx.gasPrice = ETOMIC_GASMULT * exp10<9>(); - tx.nonce = getNonce(from); + tx.nonce = getNonce(input.owner); std::stringstream ss; ss << "0x095ea7b3" << "000000000000000000000000" - << toHex(jsToAddress("0xe1D4236C5774D35Dc47dcc2E5E0CcFc463A3289c")) - << toHex(toBigEndian(jsToU256(amount))); + << toHex(jsToAddress(input.spender)) + << toHex(toBigEndian(jsToU256(input.amount))); tx.data = jsToBytes(ss.str()); - char* rawTx = signTx(tx, secret); + char* rawTx = signTx(tx, input.secret); char* result = sendRawTx(rawTx); free(rawTx); return result; } -char* aliceSendsEthPayment(AliceSendsEthPaymentInput input, BasicTxData txData) +std::stringstream aliceSendsEthPaymentData(AliceSendsEthPaymentInput input) { - TransactionSkeleton tx = txDataToSkeleton(txData); std::stringstream ss; ss << "0x47c7b6e2" << toHex(jsToBytes(input.dealId)) @@ -76,6 +75,13 @@ char* aliceSendsEthPayment(AliceSendsEthPaymentInput input, BasicTxData txData) << "000000000000000000000000" << toHex(jsToBytes(input.bobHash)) << "000000000000000000000000"; + return ss; +} + +char* aliceSendsEthPayment(AliceSendsEthPaymentInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss = aliceSendsEthPaymentData(input); tx.data = jsToBytes(ss.str()); char *rawTx = signTx(tx, txData.secretKey); char *result = sendRawTx(rawTx); @@ -83,9 +89,17 @@ char* aliceSendsEthPayment(AliceSendsEthPaymentInput input, BasicTxData txData) return result; } -char* aliceSendsErc20Payment(AliceSendsErc20PaymentInput input, BasicTxData txData) +uint8_t verifyAliceEthPaymentData(AliceSendsEthPaymentInput input, char *data) +{ + std::stringstream ss = aliceSendsEthPaymentData(input); + if (strcmp(ss.str().c_str(), data) != 0) { + return 0; + } + return 1; +} + +std::stringstream aliceSendsErc20PaymentData(AliceSendsErc20PaymentInput input) { - TransactionSkeleton tx = txDataToSkeleton(txData); std::stringstream ss; ss << "0x184db3bf" << toHex(jsToBytes(input.dealId)) @@ -98,6 +112,13 @@ char* aliceSendsErc20Payment(AliceSendsErc20PaymentInput input, BasicTxData txDa << "000000000000000000000000" << "000000000000000000000000" << toHex(jsToAddress(input.tokenAddress)); + return ss; +} + +char* aliceSendsErc20Payment(AliceSendsErc20PaymentInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss = aliceSendsErc20PaymentData(input); tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); char* result = sendRawTx(rawTx); @@ -105,6 +126,15 @@ char* aliceSendsErc20Payment(AliceSendsErc20PaymentInput input, BasicTxData txDa return result; } +uint8_t verifyAliceErc20PaymentData(AliceSendsErc20PaymentInput input, char *data) +{ + std::stringstream ss = aliceSendsErc20PaymentData(input); + if (strcmp(ss.str().c_str(), data) != 0) { + return 0; + } + return 1; +} + char* aliceReclaimsAlicePayment(AliceReclaimsAlicePaymentInput input, BasicTxData txData) { TransactionSkeleton tx = txDataToSkeleton(txData); @@ -151,9 +181,8 @@ char* bobSpendsAlicePayment(BobSpendsAlicePaymentInput input, BasicTxData txData return result; } -char* bobSendsEthDeposit(BobSendsEthDepositInput input, BasicTxData txData) +std::stringstream bobSendsEthDepositData(BobSendsEthDepositInput input) { - TransactionSkeleton tx = txDataToSkeleton(txData); std::stringstream ss; ss << "0xc2c5143f" << toHex(jsToBytes(input.depositId)) @@ -161,6 +190,13 @@ char* bobSendsEthDeposit(BobSendsEthDepositInput input, BasicTxData txData) << toHex(jsToAddress(input.aliceAddress)) << toHex(jsToBytes(input.bobHash)) << "000000000000000000000000"; + return ss; +} + +char* bobSendsEthDeposit(BobSendsEthDepositInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss = bobSendsEthDepositData(input); tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); char* result = sendRawTx(rawTx); @@ -168,9 +204,17 @@ char* bobSendsEthDeposit(BobSendsEthDepositInput input, BasicTxData txData) return result; } -char* bobSendsErc20Deposit(BobSendsErc20DepositInput input, BasicTxData txData) +uint8_t verifyBobEthDepositData(BobSendsEthDepositInput input, char *data) +{ + std::stringstream ss = bobSendsEthDepositData(input); + if (strcmp(ss.str().c_str(), data) != 0) { + return 0; + } + return 1; +} + +std::stringstream bobSendsErc20DepositData(BobSendsErc20DepositInput input) { - TransactionSkeleton tx = txDataToSkeleton(txData); std::stringstream ss; ss << "0xce8bbe4b" << toHex(jsToBytes(input.depositId)) @@ -181,6 +225,13 @@ char* bobSendsErc20Deposit(BobSendsErc20DepositInput input, BasicTxData txData) << "000000000000000000000000" << "000000000000000000000000" << toHex(jsToAddress(input.tokenAddress)); + return ss; +} + +char* bobSendsErc20Deposit(BobSendsErc20DepositInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss = bobSendsErc20DepositData(input); tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); char* result = sendRawTx(rawTx); @@ -188,6 +239,15 @@ char* bobSendsErc20Deposit(BobSendsErc20DepositInput input, BasicTxData txData) return result; } +uint8_t verifyBobErc20DepositData(BobSendsErc20DepositInput input, char *data) +{ + std::stringstream ss = bobSendsErc20DepositData(input); + if (strcmp(ss.str().c_str(), data) != 0) { + return 0; + } + return 1; +} + char* bobRefundsDeposit(BobRefundsDepositInput input, BasicTxData txData) { TransactionSkeleton tx = txDataToSkeleton(txData); @@ -231,9 +291,8 @@ char* aliceClaimsBobDeposit(AliceClaimsBobDepositInput input, BasicTxData txData return result; } -char* bobSendsEthPayment(BobSendsEthPaymentInput input, BasicTxData txData) +std::stringstream bobSendsEthPaymentData(BobSendsEthPaymentInput input) { - TransactionSkeleton tx = txDataToSkeleton(txData); std::stringstream ss; ss << "0xcf36fe8e" << toHex(jsToBytes(input.paymentId)) @@ -241,6 +300,13 @@ char* bobSendsEthPayment(BobSendsEthPaymentInput input, BasicTxData txData) << toHex(jsToAddress(input.aliceAddress)) << toHex(jsToBytes(input.aliceHash)) << "000000000000000000000000"; + return ss; +} + +char* bobSendsEthPayment(BobSendsEthPaymentInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss = bobSendsEthPaymentData(input); tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); char* result = sendRawTx(rawTx); @@ -248,9 +314,17 @@ char* bobSendsEthPayment(BobSendsEthPaymentInput input, BasicTxData txData) return result; } -char* bobSendsErc20Payment(BobSendsErc20PaymentInput input, BasicTxData txData) +uint8_t verifyBobEthPaymentData(BobSendsEthPaymentInput input, char *data) +{ + std::stringstream ss = bobSendsEthPaymentData(input); + if (strcmp(ss.str().c_str(), data) != 0) { + return 0; + } + return 1; +} + +std::stringstream bobSendsErc20PaymentData(BobSendsErc20PaymentInput input) { - TransactionSkeleton tx = txDataToSkeleton(txData); std::stringstream ss; ss << "0x34f64dfd" << toHex(jsToBytes(input.paymentId)) @@ -261,6 +335,13 @@ char* bobSendsErc20Payment(BobSendsErc20PaymentInput input, BasicTxData txData) << "000000000000000000000000" << "000000000000000000000000" << toHex(jsToAddress(input.tokenAddress)); + return ss; +} + +char* bobSendsErc20Payment(BobSendsErc20PaymentInput input, BasicTxData txData) +{ + TransactionSkeleton tx = txDataToSkeleton(txData); + std::stringstream ss = bobSendsErc20PaymentData(input); tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); char* result = sendRawTx(rawTx); @@ -268,6 +349,15 @@ char* bobSendsErc20Payment(BobSendsErc20PaymentInput input, BasicTxData txData) return result; } +uint8_t verifyBobErc20PaymentData(BobSendsErc20PaymentInput input, char *data) +{ + std::stringstream ss = bobSendsErc20PaymentData(input); + if (strcmp(ss.str().c_str(), data) != 0) { + return 0; + } + return 1; +} + char* bobReclaimsBobPayment(BobReclaimsBobPaymentInput input, BasicTxData txData) { TransactionSkeleton tx = txDataToSkeleton(txData); @@ -344,7 +434,7 @@ uint64_t getEthBalance(char* address) return static_cast(balance); } -uint64_t getErc20Balance(char* address, char* tokenAddress) +uint64_t getErc20Balance(char *address, char *tokenAddress) { std::stringstream ss; ss << "0x70a08231" @@ -358,6 +448,30 @@ uint64_t getErc20Balance(char* address, char* tokenAddress) return static_cast(balance); } +uint64_t getErc20Allowance(char *owner, char *spender, char *tokenAddress) +{ + std::stringstream ss; + ss << "0xdd62ed3e" + << "000000000000000000000000" + << toHex(jsToAddress(owner)) + << "000000000000000000000000" + << toHex(jsToAddress(spender)); + char* hexAllowance = ethCall(tokenAddress, ss.str().c_str()); + // convert wei to satoshi + u256 allowance = jsToU256(hexAllowance) / exp10<10>(); + free(hexAllowance); + return static_cast(allowance); +} + +uint8_t getErc20Decimals(char *tokenAddress) +{ + char* hexDecimals = ethCall(tokenAddress, "0x313ce567"); + // convert wei to satoshi + auto decimals = (uint8_t) strtol(hexDecimals, NULL, 0); + free(hexDecimals); + return decimals; +} + void uint8arrayToHex(char *dest, uint8_t *input, int len) { strcpy(dest, "0x"); diff --git a/iguana/exchanges/etomicswap/etomiclib.h b/iguana/exchanges/etomicswap/etomiclib.h index fba03e4e1..015cca1dd 100644 --- a/iguana/exchanges/etomicswap/etomiclib.h +++ b/iguana/exchanges/etomicswap/etomiclib.h @@ -9,16 +9,16 @@ extern "C" { #define ETOMIC_TESTNET #ifdef ETOMIC_TESTNET -#define ETOMIC_ALICECONTRACT "0xe1D4236C5774D35Dc47dcc2E5E0CcFc463A3289c" -#define ETOMIC_BOBCONTRACT "0x9387Fd3a016bB0205e4e131Dde886B9d2BC000A2" +#define ETOMIC_ALICECONTRACT "0xe1d4236c5774d35dc47dcc2e5e0ccfc463a3289c" +#define ETOMIC_BOBCONTRACT "0x9387fd3a016bb0205e4e131dde886b9d2bc000a2" #define ETOMIC_GASMULT 100 #else #define ETOMIC_ALICECONTRACT "0x9bC5418CEdED51dB08467fc4b62F32C5D9EBdA55" #define ETOMIC_BOBCONTRACT "0xB1Ad803ea4F57401639c123000C75F5B66E4D123" #define ETOMIC_GASMULT 4 #endif - -#define ETOMIC_SATOSHICAT "0000000000" + +#define EMPTY_ETH_TX_ID "0x0000000000000000000000000000000000000000000000000000000000000000" typedef struct { char from[65]; @@ -125,24 +125,57 @@ typedef struct { char bobCanClaimAfter[100]; } AliceSpendsBobPaymentInput; -char* approveErc20(char amount[100], char* from, char* secret); +typedef struct { + char tokenAddress[65]; + char owner[65]; + char spender[65]; + char amount[100]; + char secret[70]; +} ApproveErc20Input; + +char* approveErc20(ApproveErc20Input input); + char* aliceSendsEthPayment(AliceSendsEthPaymentInput input, BasicTxData txData); +uint8_t verifyAliceEthPaymentData(AliceSendsEthPaymentInput input, char *data); + char* aliceSendsErc20Payment(AliceSendsErc20PaymentInput input, BasicTxData txData); +uint8_t verifyAliceErc20PaymentData(AliceSendsErc20PaymentInput input, char *data); + char* aliceReclaimsAlicePayment(AliceReclaimsAlicePaymentInput input, BasicTxData txData); char* bobSpendsAlicePayment(BobSpendsAlicePaymentInput input, BasicTxData txData); + char* bobSendsEthDeposit(BobSendsEthDepositInput input, BasicTxData txData); +uint8_t verifyBobEthDepositData(BobSendsEthDepositInput input, char *data); + char* bobSendsErc20Deposit(BobSendsErc20DepositInput input, BasicTxData txData); +uint8_t verifyBobErc20DepositData(BobSendsErc20DepositInput input, char *data); + char* bobRefundsDeposit(BobRefundsDepositInput input, BasicTxData txData); char* aliceClaimsBobDeposit(AliceClaimsBobDepositInput input, BasicTxData txData); + char* bobSendsEthPayment(BobSendsEthPaymentInput input, BasicTxData txData); +uint8_t verifyBobEthPaymentData(BobSendsEthPaymentInput input, char *data); + char* bobSendsErc20Payment(BobSendsErc20PaymentInput input, BasicTxData txData); +uint8_t verifyBobErc20PaymentData(BobSendsErc20PaymentInput input, char *data); + char* bobReclaimsBobPayment(BobReclaimsBobPaymentInput input, BasicTxData txData); char* aliceSpendsBobPayment(AliceSpendsBobPaymentInput input, BasicTxData txData); + char* privKey2Addr(char* privKey); char* pubKey2Addr(char* pubKey); char* getPubKeyFromPriv(char* privKey); + +// returns satoshis, not wei! uint64_t getEthBalance(char* address); +// returns satoshis, not wei! uint64_t getErc20Balance(char* address, char tokenAddress[65]); + +uint8_t getErc20Decimals(char *tokenAddress); + +// returns satoshis, not wei! +uint64_t getErc20Allowance(char *owner, char *spender, char *tokenAddress); + void uint8arrayToHex(char *dest, uint8_t *input, int len); void satoshisToWei(char *dest, uint64_t input); // Your prototype or Definition