diff --git a/src/abi/ERC20.abi.json b/src/abi/ERC20.abi.json new file mode 100644 index 0000000..694c759 --- /dev/null +++ b/src/abi/ERC20.abi.json @@ -0,0 +1,303 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "initialBalance_", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "feeReceiver_", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/config.rs b/src/config.rs index a58422e..25cc841 100644 --- a/src/config.rs +++ b/src/config.rs @@ -13,6 +13,8 @@ pub struct Config { #[serde_as(as = "DisplayFromStr")] pub escrow_subgraph: Url, pub graph_env: String, + pub grt_contract: Address, + pub grt_allowance: u64, pub kafka: Kafka, #[serde_as(as = "DisplayFromStr")] pub network_subgraph: Url, diff --git a/src/main.rs b/src/main.rs index 2374813..fb931e9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,6 +30,7 @@ use crate::receipts::track_receipts; #[global_allocator] static ALLOC: snmalloc_rs::SnMalloc = snmalloc_rs::SnMalloc; +abigen!(ERC20, "src/abi/ERC20.abi.json"); abigen!(Escrow, "src/abi/Escrow.abi.json"); const GRT: u128 = 1_000_000_000_000_000_000; @@ -61,10 +62,14 @@ async fn main() -> anyhow::Result<()> { .build()?, )); let provider = Arc::new(SignerMiddleware::new(provider, sender.clone())); - let contract = Escrow::new( + let escrow = Escrow::new( ethers::abi::Address::from(config.escrow_contract.0 .0), provider.clone(), ); + let token = ERC20::new( + ethers::abi::Address::from(config.grt_contract.0 .0), + provider.clone(), + ); let http_client = reqwest::Client::builder() .timeout(Duration::from_secs(10)) @@ -105,7 +110,7 @@ async fn main() -> anyhow::Result<()> { signature.s.to_big_endian(&mut proof[32..64]); proof[64] = signature.v as u8; let proof: Bytes = proof.into(); - let tx = contract.authorize_signer(signer.address(), deadline, proof); + let tx = escrow.authorize_signer(signer.address(), deadline, proof); match tx.send().await { Ok(result) => { result.await.context("authorize tx provider error")?; @@ -124,6 +129,24 @@ async fn main() -> anyhow::Result<()> { tracing::info!(signer = %signer.address(), "authorized"); } + let allowance = token + .allowance(sender.address(), escrow.address()) + .await + .context("get allowance")?; + let expected_allowance = U256::from(config.grt_allowance as u128 * GRT); + tracing::info!(allowance = allowance.as_u128() as f64 * 1e-18); + if allowance < expected_allowance { + token + .approve(escrow.address(), expected_allowance) + .await + .context("approve")?; + } + let allowance = token + .allowance(sender.address(), escrow.address()) + .await + .context("get allowance")?; + tracing::info!(allowance = allowance.as_u128() as f64 * 1e-18); + let debts = track_receipts(&config.kafka, config.graph_env) .await .context("failed to start kafka client")?; @@ -181,7 +204,7 @@ async fn main() -> anyhow::Result<()> { .collect(); let amounts: Vec = adjustments.iter().map(|(_, a)| U256::from(*a)).collect(); - let tx = contract.deposit_many(receivers, amounts); + let tx = escrow.deposit_many(receivers, amounts); let pending = match tx.send().await { Ok(pending) => pending, Err(contract_call_err) => { @@ -339,7 +362,7 @@ mod tests { fn next_balance() { let tests = [ (0, MIN_DEPOSIT), - (1 * GRT, MIN_DEPOSIT), + (GRT, MIN_DEPOSIT), (MIN_DEPOSIT / 2, MIN_DEPOSIT), (MIN_DEPOSIT, MIN_DEPOSIT * 2), (MIN_DEPOSIT + 1, MIN_DEPOSIT * 2),