Skip to content

Commit

Permalink
Ported to alloy, deprecate rust-web3, treasury transfer
Browse files Browse the repository at this point in the history
- Deprecated rust-web3 in favor of alloy-rs due to rust-web3 being deprecated in the future
- Replaced eth abi with IERC20 abi.
- Transfer paid invoice funds to treasury when paid

TODO: in the near future token transfers also need to be included so that it is possible to configure payments via tokens.
  • Loading branch information
saefstroem committed May 8, 2024
1 parent 4ad607b commit af0fcdf
Show file tree
Hide file tree
Showing 12 changed files with 651 additions and 559 deletions.
537 changes: 59 additions & 478 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
alloy = { git = "https://github.com/alloy-rs/alloy", version = "0.1.0",features=["signers","signer-wallet"] }
alloy = { git = "https://github.com/alloy-rs/alloy", version = "0.1.0",features=["rpc-types-eth","eips","signers","signer-wallet","consensus","network","providers","transports","transport-http","contract"] }
bincode = "1.3.3"
sled = "0.34.7"
thiserror = "1.0.59"
web3 = "0.19.0"
serde = { version="1.0.197",features=["derive"] }
sha2 = "0.10.8"
tokio = "1.37.0"
uuid = {version="1.8.0",features=["v4"]}
reqwest = "0.12.4"
279 changes: 279 additions & 0 deletions src/abi/IERC20.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
[
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "guy",
"type": "address"
},
{
"name": "wad",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "src",
"type": "address"
},
{
"name": "dst",
"type": "address"
},
{
"name": "wad",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "wad",
"type": "uint256"
}
],
"name": "withdraw",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [
{
"name": "",
"type": "uint8"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "dst",
"type": "address"
},
{
"name": "wad",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "deposit",
"outputs": [],
"payable": true,
"stateMutability": "payable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
},
{
"name": "",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"payable": true,
"stateMutability": "payable",
"type": "fallback"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "src",
"type": "address"
},
{
"indexed": true,
"name": "guy",
"type": "address"
},
{
"indexed": false,
"name": "wad",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "src",
"type": "address"
},
{
"indexed": true,
"name": "dst",
"type": "address"
},
{
"indexed": false,
"name": "wad",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "dst",
"type": "address"
},
{
"indexed": false,
"name": "wad",
"type": "uint256"
}
],
"name": "Deposit",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "src",
"type": "address"
},
{
"indexed": false,
"name": "wad",
"type": "uint256"
}
],
"name": "Withdrawal",
"type": "event"
}
]
1 change: 0 additions & 1 deletion src/erc20/abi.rs

This file was deleted.

63 changes: 31 additions & 32 deletions src/erc20/mod.rs
Original file line number Diff line number Diff line change
@@ -1,65 +1,64 @@
mod abi;
use web3::{
contract::{Contract, Options},
transports::Http,
types::{Address, U256},
Web3,
use alloy::{
contract::Error, primitives::Uint, providers::RootProvider, sol, transports::http::Http,
};
use reqwest::Client;

use std::str::FromStr;
use self::IERC20::IERC20Instance;

sol!(
#[allow(missing_docs)]
#[sol(rpc)]
IERC20,
"src/abi/IERC20.json"
);

use self::abi::ERC20_ABI;
#[derive(Clone)]
pub struct ERC20Token {
contract: Contract<Http>,
pub contract: IERC20Instance<Http<Client>, RootProvider<Http<Client>>>,
}

impl ERC20Token {
/// Creates a new instance of an ERC20 token. This is just a wrapper
/// function to simplify the interactions with contracts.
pub fn new(web3: Web3<Http>, token_address: String) -> ERC20Token {
let contract = Contract::from_json(
web3.eth(),
token_address.parse().unwrap(),
ERC20_ABI.as_bytes(),
)
.unwrap();
pub fn new(provider: RootProvider<Http<Client>>, token_address: String) -> ERC20Token {
let contract = IERC20::new(token_address.parse().unwrap(), provider);
ERC20Token { contract }
}

/// Retrieves the token balance of a specified address
pub async fn get_balance(&self, address: String) -> Result<U256, web3::contract::Error> {
self.contract
.query(
"balanceOf",
Address::from_str(&address).unwrap(),
None,
Options::default(),
None,
)
.await
pub async fn get_balance(&self, address: String) -> Result<Uint<256, 4>, Error> {
let IERC20::balanceOfReturn { _0 } = self
.contract
.balanceOf(address.parse().unwrap())
.call()
.await?;
Ok(_0)
}
}

#[cfg(test)]
mod tests {
use web3::{transports::Http, types::U256, Web3};

use crate::erc20::ERC20Token;
use std::str::FromStr;

use alloy::{primitives::U256, providers::ProviderBuilder};
use reqwest::Url;

use crate::erc20::ERC20Token;
#[tokio::test]
async fn valid_balance() {
let http = Http::new("https://bsc-dataseed1.binance.org/").unwrap();
let web3 = Web3::new(http);
let provider = ProviderBuilder::new()
.on_http(Url::from_str("https://bsc-dataseed1.binance.org/").unwrap());

let token = ERC20Token::new(
web3,
provider,
"0x2170ed0880ac9a755fd29b2688956bd959f933f8".to_string(),
);
let balance = token
.get_balance("0xC882b111A75C0c657fC507C04FbFcD2cC984F071".to_string())
.await
.unwrap();
println!("Balance check: {}", balance);
assert!(balance.ge(&U256::zero()));
assert!(balance.ge(&U256::from_str("0").unwrap()));
}
}
Loading

0 comments on commit af0fcdf

Please sign in to comment.