diff --git a/Cargo.lock b/Cargo.lock index 73a60ba0a6..4684ce228f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1869,8 +1869,7 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "erc20_payment_lib" version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87089d68e729591f5fe8a4d2c9d4cb565fd552af42d97161bbabe3cf6fa65a2d" +source = "git+https://github.com/golemfactory/erc20_payment_lib?rev=101e6bf331db3fd6b2b55813abc9ccccbc4960b7#101e6bf331db3fd6b2b55813abc9ccccbc4960b7" dependencies = [ "actix-files", "actix-web", diff --git a/Cargo.toml b/Cargo.toml index 3cd3a3ca0c..1412878372 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -224,9 +224,9 @@ members = [ # diesel 1.4.* supports up to 0.23.0, but sqlx 0.5.9 requires 0.22.0 # sqlx 0.5.10 need 0.23.2, so 0.5.9 is last version possible libsqlite3-sys = { version = "0.26.0", features = ["bundled"] } -#erc20_payment_lib = { git = "https://github.com/golemfactory/erc20_payment_lib", rev = "f75d7a6819c64c1701c38e6551d29f15bb16e164" } +erc20_payment_lib = { git = "https://github.com/golemfactory/erc20_payment_lib", rev = "101e6bf331db3fd6b2b55813abc9ccccbc4960b7" } #erc20_payment_lib = { path = "../../payments/erc20_payment_lib/crates/erc20_payment_lib" } -erc20_payment_lib = { version = "=0.3.1" } +#erc20_payment_lib = { version = "=0.3.1" } rand = "0.8.5" url = "2.3.1" trust-dns-resolver = "0.22" diff --git a/core/payment-driver/erc20next/config-payments.toml b/core/payment-driver/erc20next/config-payments.toml index 178b868776..68602e4f6c 100644 --- a/core/payment-driver/erc20next/config-payments.toml +++ b/core/payment-driver/erc20next/config-payments.toml @@ -17,39 +17,39 @@ gather-interval = 60 # gather payments on payment driver start (otherwise wait for first gather-interval) gather-at-start = true automatic-recover = false +# set to true to not respect deadlines attached to payments +ignore-deadlines = false [chain.goerli] chain-name = "Goerli" chain-id = 5 -rpc-endpoints = [ - "https://ethereum-goerli-rpc.allthatnode.com", +rpc-endpoints = ["https://ethereum-goerli-rpc.allthatnode.com", + "https://rpc.goerli.mudit.blog", "https://rpc.slock.it/goerli", - "https://rpc.ankr.com/eth_goerli", -] + "https://www.ethercluster.com/goerli", + "https://rpc.ankr.com/eth_goerli"] currency-symbol = "tETH" -priority-fee = 1.5111 -max-fee-per-gas = 10.0 +priority-fee = 1.01 +max-fee-per-gas = 300.0 gas-left-warning-limit = 1000000 -transaction-timeout = 100 +transaction-timeout = 60 token = { address = "0x33af15c79d64b85ba14aaffaa4577949104b22e8", symbol = "tGLM" } -# multi-contract = { address = "0x7777784f803a7bf1d7f115f849d29ce5706da64a", max-at-once = 10 } +multi-contract = { address = "0x7777784f803a7bf1d7f115f849d29ce5706da64a", max-at-once = 10 } confirmation-blocks = 1 block-explorer-url = "https://goerli.etherscan.io" [chain.mumbai] chain-name = "Mumbai testnet" chain-id = 80001 -rpc-endpoints = [ - "https://rpc-mumbai.maticvigil.com/v1/fd04db1066cae0f44d3461ae6d6a7cbbdd46e4a5", -] +rpc-endpoints = ["https://rpc-mumbai.maticvigil.com/v1/fd04db1066cae0f44d3461ae6d6a7cbbdd46e4a5"] # rpc-endpoints = ["http://127.0.0.1:8545"] currency-symbol = "tMATIC" -priority-fee = 1.5111 -max-fee-per-gas = 500.0 +priority-fee = 1.01 +max-fee-per-gas = 300.0 gas-left-warning-limit = 1000000 -transaction-timeout = 100 +transaction-timeout = 60 token = { address = "0x2036807B0B3aaf5b1858EE822D0e111fDdac7018", symbol = "tGLM" } -# multi-contract = { address = "0x800010D7d0d315DCA795110ecCf0127cBd76b89f", max-at-once = 10 } +multi-contract = { address = "0x800010D7d0d315DCA795110ecCf0127cBd76b89f", max-at-once = 10 } confirmation-blocks = 1 block-explorer-url = "https://mumbai.polygonscan.com" @@ -61,8 +61,9 @@ currency-symbol = "MATIC" priority-fee = 30.111 max-fee-per-gas = 500.0 gas-left-warning-limit = 1000000 -transaction-timeout = 100 -token = { address = "0x2036807B0B3aaf5b1858EE822D0e111fDdac7018", symbol = "tGLM" } +transaction-timeout = 120 +token = { address = "0x0B220b82F3eA3B7F6d9A1D8ab58930C064A2b5Bf", symbol = "GLM" } # multi-contract = { address = "0x50100d4faf5f3b09987dea36dc2eddd57a3e561b", max-at-once = 10 } confirmation-blocks = 1 block-explorer-url = "https://polygonscan.com" + diff --git a/core/payment-driver/erc20next/src/driver.rs b/core/payment-driver/erc20next/src/driver.rs index c2ab5563ca..dd19b97f70 100644 --- a/core/payment-driver/erc20next/src/driver.rs +++ b/core/payment-driver/erc20next/src/driver.rs @@ -1,3 +1,4 @@ +use chrono::{DateTime, Duration, Utc}; /* Erc20Driver to handle payments on the erc20next network. @@ -5,7 +6,9 @@ */ // Extrnal crates use erc20_payment_lib::db::model::{TokenTransferDao, TxDao}; -use erc20_payment_lib::runtime::{DriverEvent, DriverEventContent, PaymentRuntime, TransferType}; +use erc20_payment_lib::runtime::{ + DriverEvent, DriverEventContent, PaymentRuntime, TransferType, VerifyTransactionResult, +}; use ethereum_types::H160; use ethereum_types::U256; use num_bigint::BigInt; @@ -88,6 +91,7 @@ impl Erc20NextDriver { to: &str, amount: &BigDecimal, network: &str, + deadline: Option>, ) -> Result { self.is_account_active(sender).await?; let sender = H160::from_str(sender) @@ -106,6 +110,7 @@ impl Erc20NextDriver { TransferType::Token, amount, &payment_id, + deadline, ) .await .map_err(|err| GenericError::new(format!("Error when inserting transfer {err:?}")))?; @@ -361,8 +366,14 @@ impl PaymentDriver for Erc20NextDriver { .network .ok_or(GenericError::new("Network not specified".to_string()))?; - self.do_transfer(&msg.sender, &msg.to, &msg.amount, &network) - .await + self.do_transfer( + &msg.sender, + &msg.to, + &msg.amount, + &network, + Some(Utc::now()), + ) + .await } async fn schedule_payment( @@ -379,8 +390,16 @@ impl PaymentDriver for Erc20NextDriver { msg.platform() )))?; - self.do_transfer(&msg.sender(), &msg.recipient(), &msg.amount(), network) - .await + let transfer_margin = Duration::minutes(2); + + self.do_transfer( + &msg.sender(), + &msg.recipient(), + &msg.amount(), + network, + Some(msg.due_date() - transfer_margin), + ) + .await } async fn verify_payment( @@ -393,7 +412,7 @@ impl PaymentDriver for Erc20NextDriver { let (network, _) = network::platform_to_network_token(msg.platform())?; let tx_hash = format!("0x{}", hex::encode(msg.confirmation().confirmation)); log::info!("Verifying transaction: {} on network {}", tx_hash, network); - let res = self + let verify_res = self .payment_runtime .verify_transaction( network as i64, @@ -408,18 +427,20 @@ impl PaymentDriver for Erc20NextDriver { .await .map_err(|err| GenericError::new(format!("Error verifying transaction: {}", err)))?; - if res.verified { - Ok(PaymentDetails { - recipient: msg.details.payee_addr.clone(), - sender: msg.details.payer_addr.clone(), - amount: msg.details.amount.clone(), - date: None, - }) - } else { - Err(GenericError::new(format!( - "Transaction not found: {}", - tx_hash - ))) + match verify_res { + VerifyTransactionResult::Verified { amount } => { + let amount_int = BigInt::from_str(&format!("{amount}")).unwrap(); + let amount = BigDecimal::new(amount_int, 18); + Ok(PaymentDetails { + recipient: msg.details.payee_addr.clone(), + sender: msg.details.payer_addr.clone(), + amount, + date: None, + }) + } + VerifyTransactionResult::Rejected(reason) => Err(GenericError::new(format!( + "Payment {tx_hash} rejected: {reason}", + ))), } } @@ -520,6 +541,17 @@ impl PaymentDriver for Erc20NextDriver { needed_gas_est: missing_gas.unwrap_or_default().to_string(), }) } + LibStatusProperty::NoToken { + chain_id, + missing_token, + } => { + let network = chain_id_to_net(chain_id); + network_filter(&network).then(|| DriverStatusProperty::InsufficientToken { + driver: DRIVER_NAME.into(), + network, + needed_token_est: missing_token.unwrap_or_default().to_string(), + }) + } }) .collect()) } diff --git a/core/payment/src/processor.rs b/core/payment/src/processor.rs index db6e6407a2..63268ee0fe 100644 --- a/core/payment/src/processor.rs +++ b/core/payment/src/processor.rs @@ -628,7 +628,7 @@ impl PaymentProcessor { let shared_payments = payment_dao .get_for_confirmation(confirmation.confirmation) .await?; - let all_payment_sum = shared_payments + let other_payment_total = shared_payments .iter() .map(|payment| { let agreement_total = payment @@ -647,8 +647,9 @@ impl PaymentProcessor { }) .sum::(); - if &all_payment_sum + agreement_sum + activity_sum > details.amount { - return VerifyPaymentError::overspending(&details.amount, &all_payment_sum); + let all_payment_total = &other_payment_total + agreement_sum + activity_sum; + if all_payment_total > details.amount { + return VerifyPaymentError::overspending(&details.amount, &all_payment_total); } // Insert payment into database (this operation creates and updates all related entities) diff --git a/core/payment/src/service.rs b/core/payment/src/service.rs index 38e5165408..ea239d8765 100644 --- a/core/payment/src/service.rs +++ b/core/payment/src/service.rs @@ -400,6 +400,7 @@ mod public { use super::*; + use crate::error::processor::VerifyPaymentError; use crate::error::DbError; use crate::payment_sync::{send_sync_notifs_job, send_sync_requests}; use crate::utils::*; @@ -818,18 +819,18 @@ mod public { .verify_payment(payment, signature) .await { - Ok(_) | Err(_) => { + Ok(_) => { counter!("payment.amount.received", ya_metrics::utils::cryptocurrency_to_u64(&amount), "platform" => platform); counter!("payment.invoices.provider.paid", num_paid_invoices); Ok(Ack {}) } - // Err(e) => match e { - // VerifyPaymentError::ConfirmationEncoding => { - // Err(SendError::BadRequest(e.to_string())) - // } - // VerifyPaymentError::Validation(e) => Err(SendError::BadRequest(e)), - // _ => Err(SendError::ServiceError(e.to_string())), - //}, + Err(e) => match e { + VerifyPaymentError::ConfirmationEncoding => { + Err(SendError::BadRequest(e.to_string())) + } + VerifyPaymentError::Validation(e) => Err(SendError::BadRequest(e)), + _ => Err(SendError::ServiceError(e.to_string())), + }, } } diff --git a/goth_tests/domain/payments/goth-config.yml b/goth_tests/domain/payments/goth-config.yml index 2cd99a6097..511ff1ce61 100644 --- a/goth_tests/domain/payments/goth-config.yml +++ b/goth_tests/domain/payments/goth-config.yml @@ -38,7 +38,6 @@ node-types: environment: - "ERC20_SENDOUT_INTERVAL_SECS=1" - "ERC20_CONFIRMATION_INTERVAL_SECS=1" - - "ERC20NEXT_SENDOUT_INTERVAL_SECS=1" - name: "Provider" class: "goth_tests.helpers.probe.ProviderProbe"