Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

give contract infinite token allowance #2275

Merged
merged 1 commit into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions evmlib/src/contract/network_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,20 @@ where
Ok(balance)
}

/// See how many tokens are approved to be spent.
pub async fn allowance(&self, owner: Address, spender: Address) -> Result<U256, Error> {
debug!("Getting allowance of owner: {owner} for spender: {spender}",);
let balance = self
.contract
.allowance(owner, spender)
.call()
.await
.inspect_err(|err| error!("Error getting allowance: {err:?}"))?
._0;
debug!("Allowance of owner: {owner} for spender: {spender} is: {balance}");
Ok(balance)
}

/// Approve spender to spend a raw amount of tokens.
pub async fn approve(&self, spender: Address, value: U256) -> Result<TxHash, Error> {
debug!("Approving spender to spend raw amt of tokens: {value}");
Expand Down
52 changes: 45 additions & 7 deletions evmlib/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@

/// Returns the raw balance of payment tokens for this wallet.
pub async fn balance_of_tokens(&self) -> Result<U256, network_token::Error> {
balance_of_tokens(wallet_address(&self.wallet), &self.network).await
balance_of_tokens(self.address(), &self.network).await
}

/// Returns the raw balance of gas tokens for this wallet.
pub async fn balance_of_gas_tokens(&self) -> Result<U256, network_token::Error> {
balance_of_gas_tokens(wallet_address(&self.wallet), &self.network).await
balance_of_gas_tokens(self.address(), &self.network).await
}

/// Transfer a raw amount of payment tokens to another address.
Expand All @@ -96,6 +96,20 @@
transfer_gas_tokens(self.wallet.clone(), &self.network, to, amount).await
}

/// See how many tokens of the owner may be spent by the spender.
pub async fn token_allowance(&self, spender: Address) -> Result<U256, network_token::Error> {
token_allowance(&self.network, self.address(), spender).await
}

/// Approve an address / smart contract to spend this wallet's payment tokens.
pub async fn approve_to_spend_tokens(
&self,
spender: Address,
amount: U256,
) -> Result<TxHash, network_token::Error> {
approve_to_spend_tokens(self.wallet.clone(), &self.network, spender, amount).await
}

/// Pays for a single quote. Returns transaction hash of the payment.
pub async fn pay_for_quote(
&self,
Expand Down Expand Up @@ -188,8 +202,20 @@
Ok(balance)
}

/// See how many tokens of the owner may be spent by the spender.
pub async fn token_allowance(
network: &Network,
owner: Address,
spender: Address,
) -> Result<U256, network_token::Error> {
debug!("Getting allowance for owner: {owner} and spender: {spender}",);
let provider = http_provider(network.rpc_url().clone());
let network_token = NetworkToken::new(*network.payment_token_address(), provider);
network_token.allowance(owner, spender).await
}

/// Approve an address / smart contract to spend this wallet's payment tokens.
async fn approve_to_spend_tokens(
pub async fn approve_to_spend_tokens(
wallet: EthereumWallet,
network: &Network,
spender: Address,
Expand Down Expand Up @@ -250,16 +276,28 @@

let mut tx_hashes_by_quote = BTreeMap::new();

// Approve the contract to spend enough of the client's tokens.
approve_to_spend_tokens(
wallet.clone(),
// Check allowance
let allowance = token_allowance(
network,
wallet_address(&wallet),
*network.data_payments_address(),
total_amount,
)
.await
.map_err(|err| PayForQuotesError(Error::from(err), tx_hashes_by_quote.clone()))?;

// TODO: Get rid of approvals altogether, by using permits or whatever..

Check notice

Code scanning / devskim

A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note

Suspicious comment
if allowance < total_amount {
// Approve the contract to spend all the client's tokens.
approve_to_spend_tokens(
wallet.clone(),
network,
*network.data_payments_address(),
U256::MAX,
)
.await
.map_err(|err| PayForQuotesError(Error::from(err), tx_hashes_by_quote.clone()))?;
}

let provider = http_provider_with_wallet(network.rpc_url().clone(), wallet);
let data_payments = DataPaymentsHandler::new(*network.data_payments_address(), provider);

Expand Down
Loading