Skip to content

Commit

Permalink
feat: fetch eth events
Browse files Browse the repository at this point in the history
  • Loading branch information
veeso committed Feb 9, 2024
1 parent 4c48fca commit d438452
Show file tree
Hide file tree
Showing 26 changed files with 423 additions and 35 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ ethers-contract = { version = "2", default-features = false, features = [
] }
ethers-core = "2"
ethers-signers = "2"
ethnum = "1"
hex = "0.4"
ic-cdk = "0.11"
ic-cdk-macros = "0.8"
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ impl TestEnv {
cketh_minter_canister,
erc20_bridge_address: H160::from_hex_str("0x2CE04Fd64DB0372F6fb4B7a542f0F9196feE5663")
.unwrap(),
erc20_gas_price: 39_000_000_000_u64.into(), // 39 gwei
erc20_gas_price: 39_000_000_000_u64, // 39 gwei
erc20_network: EthNetwork::Sepolia,
};
let init_arg = Encode!(&init_arg).unwrap();
Expand Down
12 changes: 12 additions & 0 deletions src/declarations/deferred/deferred.did.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ export type AllowanceError = { 'AllowanceNotFound' : null } |
{ 'BadExpiration' : null } |
{ 'AllowanceExpired' : null } |
{ 'InsufficientFunds' : null };
export type ApproveError = {
'GenericError' : { 'message' : string, 'error_code' : bigint }
} |
{ 'TemporarilyUnavailable' : null } |
{ 'Duplicate' : { 'duplicate_of' : bigint } } |
{ 'BadFee' : { 'expected_fee' : bigint } } |
{ 'AllowanceChanged' : { 'current_allowance' : bigint } } |
{ 'CreatedInFuture' : { 'ledger_time' : bigint } } |
{ 'TooOld' : null } |
{ 'Expired' : { 'ledger_time' : bigint } } |
{ 'InsufficientFunds' : { 'balance' : bigint } };
export type BalanceError = { 'AccountNotFound' : null } |
{ 'InsufficientBalance' : null };
export type ConfigurationError = { 'AdminsCantBeEmpty' : null } |
Expand Down Expand Up @@ -53,6 +64,7 @@ export type EcdsaError = { 'RecoveryIdError' : null } |
{ 'InvalidSignature' : null } |
{ 'InvalidPublicKey' : null };
export type EkokeError = { 'Configuration' : ConfigurationError } |
{ 'Icrc2Approve' : ApproveError } |
{ 'Icrc1Transfer' : TransferError } |
{ 'Pool' : PoolError } |
{ 'Allowance' : AllowanceError } |
Expand Down
15 changes: 15 additions & 0 deletions src/declarations/deferred/deferred.did.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ export const idlFactory = ({ IDL }) => {
'AdminsCantBeEmpty' : IDL.Null,
'AnonymousAdmin' : IDL.Null,
});
const ApproveError = IDL.Variant({
'GenericError' : IDL.Record({
'message' : IDL.Text,
'error_code' : IDL.Nat,
}),
'TemporarilyUnavailable' : IDL.Null,
'Duplicate' : IDL.Record({ 'duplicate_of' : IDL.Nat }),
'BadFee' : IDL.Record({ 'expected_fee' : IDL.Nat }),
'AllowanceChanged' : IDL.Record({ 'current_allowance' : IDL.Nat }),
'CreatedInFuture' : IDL.Record({ 'ledger_time' : IDL.Nat64 }),
'TooOld' : IDL.Null,
'Expired' : IDL.Record({ 'ledger_time' : IDL.Nat64 }),
'InsufficientFunds' : IDL.Record({ 'balance' : IDL.Nat }),
});
const TransferError = IDL.Variant({
'GenericError' : IDL.Record({
'message' : IDL.Text,
Expand Down Expand Up @@ -82,6 +96,7 @@ export const idlFactory = ({ IDL }) => {
});
const EkokeError = IDL.Variant({
'Configuration' : ConfigurationError,
'Icrc2Approve' : ApproveError,
'Icrc1Transfer' : TransferError,
'Pool' : PoolError,
'Allowance' : AllowanceError,
Expand Down
1 change: 1 addition & 0 deletions src/declarations/ekoke/ekoke.did.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export type EcdsaError = { 'RecoveryIdError' : null } |
{ 'InvalidSignature' : null } |
{ 'InvalidPublicKey' : null };
export type EkokeError = { 'Configuration' : ConfigurationError } |
{ 'Icrc2Approve' : ApproveError } |
{ 'Icrc1Transfer' : TransferError } |
{ 'Pool' : PoolError } |
{ 'Allowance' : AllowanceError } |
Expand Down
29 changes: 15 additions & 14 deletions src/declarations/ekoke/ekoke.did.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,20 @@ export const idlFactory = ({ IDL }) => {
'AdminsCantBeEmpty' : IDL.Null,
'AnonymousAdmin' : IDL.Null,
});
const ApproveError = IDL.Variant({
'GenericError' : IDL.Record({
'message' : IDL.Text,
'error_code' : IDL.Nat,
}),
'TemporarilyUnavailable' : IDL.Null,
'Duplicate' : IDL.Record({ 'duplicate_of' : IDL.Nat }),
'BadFee' : IDL.Record({ 'expected_fee' : IDL.Nat }),
'AllowanceChanged' : IDL.Record({ 'current_allowance' : IDL.Nat }),
'CreatedInFuture' : IDL.Record({ 'ledger_time' : IDL.Nat64 }),
'TooOld' : IDL.Null,
'Expired' : IDL.Record({ 'ledger_time' : IDL.Nat64 }),
'InsufficientFunds' : IDL.Record({ 'balance' : IDL.Nat }),
});
const TransferError = IDL.Variant({
'GenericError' : IDL.Record({
'message' : IDL.Text,
Expand Down Expand Up @@ -89,6 +103,7 @@ export const idlFactory = ({ IDL }) => {
});
const EkokeError = IDL.Variant({
'Configuration' : ConfigurationError,
'Icrc2Approve' : ApproveError,
'Icrc1Transfer' : TransferError,
'Pool' : PoolError,
'Allowance' : AllowanceError,
Expand Down Expand Up @@ -162,20 +177,6 @@ export const idlFactory = ({ IDL }) => {
'expires_at' : IDL.Opt(IDL.Nat64),
'spender' : Account,
});
const ApproveError = IDL.Variant({
'GenericError' : IDL.Record({
'message' : IDL.Text,
'error_code' : IDL.Nat,
}),
'TemporarilyUnavailable' : IDL.Null,
'Duplicate' : IDL.Record({ 'duplicate_of' : IDL.Nat }),
'BadFee' : IDL.Record({ 'expected_fee' : IDL.Nat }),
'AllowanceChanged' : IDL.Record({ 'current_allowance' : IDL.Nat }),
'CreatedInFuture' : IDL.Record({ 'ledger_time' : IDL.Nat64 }),
'TooOld' : IDL.Null,
'Expired' : IDL.Record({ 'ledger_time' : IDL.Nat64 }),
'InsufficientFunds' : IDL.Record({ 'balance' : IDL.Nat }),
});
const Result_5 = IDL.Variant({ 'Ok' : IDL.Nat, 'Err' : ApproveError });
const TransferFromArgs = IDL.Record({
'to' : Account,
Expand Down
12 changes: 12 additions & 0 deletions src/declarations/marketplace/marketplace.did.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ export type AllowanceError = { 'AllowanceNotFound' : null } |
{ 'BadExpiration' : null } |
{ 'AllowanceExpired' : null } |
{ 'InsufficientFunds' : null };
export type ApproveError = {
'GenericError' : { 'message' : string, 'error_code' : bigint }
} |
{ 'TemporarilyUnavailable' : null } |
{ 'Duplicate' : { 'duplicate_of' : bigint } } |
{ 'BadFee' : { 'expected_fee' : bigint } } |
{ 'AllowanceChanged' : { 'current_allowance' : bigint } } |
{ 'CreatedInFuture' : { 'ledger_time' : bigint } } |
{ 'TooOld' : null } |
{ 'Expired' : { 'ledger_time' : bigint } } |
{ 'InsufficientFunds' : { 'balance' : bigint } };
export type BalanceError = { 'AccountNotFound' : null } |
{ 'InsufficientBalance' : null };
export type BuyError = { 'TokenHasNoOwner' : null } |
Expand All @@ -28,6 +39,7 @@ export type EcdsaError = { 'RecoveryIdError' : null } |
{ 'InvalidSignature' : null } |
{ 'InvalidPublicKey' : null };
export type EkokeError = { 'Configuration' : ConfigurationError } |
{ 'Icrc2Approve' : ApproveError } |
{ 'Icrc1Transfer' : TransferError } |
{ 'Pool' : PoolError } |
{ 'Allowance' : AllowanceError } |
Expand Down
15 changes: 15 additions & 0 deletions src/declarations/marketplace/marketplace.did.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,20 @@ export const idlFactory = ({ IDL }) => {
'OwnerNotFound' : IDL.Null,
'Other' : IDL.Text,
});
const ApproveError = IDL.Variant({
'GenericError' : IDL.Record({
'message' : IDL.Text,
'error_code' : IDL.Nat,
}),
'TemporarilyUnavailable' : IDL.Null,
'Duplicate' : IDL.Record({ 'duplicate_of' : IDL.Nat }),
'BadFee' : IDL.Record({ 'expected_fee' : IDL.Nat }),
'AllowanceChanged' : IDL.Record({ 'current_allowance' : IDL.Nat }),
'CreatedInFuture' : IDL.Record({ 'ledger_time' : IDL.Nat64 }),
'TooOld' : IDL.Null,
'Expired' : IDL.Record({ 'ledger_time' : IDL.Nat64 }),
'InsufficientFunds' : IDL.Record({ 'balance' : IDL.Nat }),
});
const PoolError = IDL.Variant({
'PoolNotFound' : IDL.Nat,
'NotEnoughTokens' : IDL.Null,
Expand Down Expand Up @@ -88,6 +102,7 @@ export const idlFactory = ({ IDL }) => {
});
const EkokeError = IDL.Variant({
'Configuration' : ConfigurationError,
'Icrc2Approve' : ApproveError,
'Icrc1Transfer' : TransferError,
'Pool' : PoolError,
'Allowance' : AllowanceError,
Expand Down
12 changes: 12 additions & 0 deletions src/deferred/deferred.did
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ type AllowanceError = variant {
AllowanceExpired;
InsufficientFunds;
};
type ApproveError = variant {
GenericError : record { message : text; error_code : nat };
TemporarilyUnavailable;
Duplicate : record { duplicate_of : nat };
BadFee : record { expected_fee : nat };
AllowanceChanged : record { current_allowance : nat };
CreatedInFuture : record { ledger_time : nat64 };
TooOld;
Expired : record { ledger_time : nat64 };
InsufficientFunds : record { balance : nat };
};
type BalanceError = variant { AccountNotFound; InsufficientBalance };
type ConfigurationError = variant { AdminsCantBeEmpty; AnonymousAdmin };
type ConfigurationError_1 = variant {
Expand Down Expand Up @@ -56,6 +67,7 @@ type EcdsaError = variant {
};
type EkokeError = variant {
Configuration : ConfigurationError;
Icrc2Approve : ApproveError;
Icrc1Transfer : TransferError;
Pool : PoolError;
Allowance : AllowanceError;
Expand Down
1 change: 1 addition & 0 deletions src/ekoke/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ did = { path = "../did" }
ethers-contract = { workspace = true }
ethers-core = { workspace = true }
ethers-signers = { workspace = true }
ethnum = { workspace = true }
ic-cdk = { workspace = true }
ic-cdk-macros = { workspace = true }
ic-cdk-timers = { workspace = true }
Expand Down
1 change: 1 addition & 0 deletions src/ekoke/ekoke.did
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type EcdsaError = variant {
};
type EkokeError = variant {
Configuration : ConfigurationError;
Icrc2Approve : ApproveError;
Icrc1Transfer : TransferError;
Pool : PoolError;
Allowance : AllowanceError;
Expand Down
13 changes: 13 additions & 0 deletions src/ekoke/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ impl EkokeCanister {
let _ = Erc20Bridge::withdraw_cketh_to_eth().await;
}

#[cfg(target_family = "wasm")]
async fn fetch_ekoke_swapped_events() {
let _ = Erc20Bridge::swap_erc20_to_icrc().await;
}

#[cfg(target_family = "wasm")]
let fetch_gas_price_timer_interval =
crate::constants::THREE_HOURS + std::time::Duration::from_secs(60);
Expand All @@ -125,6 +130,14 @@ impl EkokeCanister {
ic_cdk_timers::set_timer_interval(crate::constants::CKETH_WITHDRAWAL_INTERVAL, || {
ic_cdk::spawn(convert_cketh_to_eth_timer());
});
// Fetch ERC20 -> ICRC swap events
#[cfg(target_family = "wasm")]
ic_cdk_timers::set_timer_interval(
crate::constants::ERC20_SWAPPED_EVENT_FETCH_INTERVAL,
|| {
ic_cdk::spawn(fetch_ekoke_swapped_events());
},
);
}

/// Get transaction by id
Expand Down
2 changes: 1 addition & 1 deletion src/ekoke/src/app/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl Balance {
Some(balance) => balance,
None => {
// If balance is not set, create it with 0 balance
balances.insert(storable_account.clone(), AccountBalance::from(Nat::from(0)));
balances.insert(storable_account, AccountBalance::from(Nat::from(0)));
balances.get(&storable_account).unwrap()
}
};
Expand Down
46 changes: 44 additions & 2 deletions src/ekoke/src/app/erc20_bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ mod gas_station;
mod swap_fee;
mod swap_pool;

use std::cell::RefCell;

use did::ekoke::{BalanceError, EkokeError, EkokeResult, PicoEkoke};
use did::H160;
use ic_stable_structures::memory_manager::VirtualMemory;
use ic_stable_structures::{DefaultMemoryImpl, StableCell};
use icrc::icrc1::account::Account;

use self::eth_rpc::EthRpcClient;
Expand All @@ -16,6 +20,18 @@ use self::swap_fee::SwapFee;
use self::swap_pool::SwapPool;
use super::balance::Balance;
use super::configuration::Configuration;
use crate::app::memory::{ERC20_LOGS_START_BLOCK_MEMORY_ID, MEMORY_MANAGER};

thread_local! {
/// ERC20 logs start block
static ERC20_LOGS_START_BLOCK: RefCell<StableCell<u64, VirtualMemory<DefaultMemoryImpl>>> =
RefCell::new(
StableCell::new(
MEMORY_MANAGER.with(|mm| mm.get(ERC20_LOGS_START_BLOCK_MEMORY_ID)),
0,
).unwrap()
);
}

/// ERC20 Bridge
pub struct Erc20Bridge;
Expand Down Expand Up @@ -57,12 +73,35 @@ impl Erc20Bridge {
Ok(hash)
}

/// Get the Ekoke Swap event and then
///
/// Swaps the ERC20 FLY token to the ICRC FLY token.
///
/// This method is easier than the conversion from ICRC FLY to ERC20 FLY and it basically
/// just transfer the amount from the swap pool to the recipient.
pub async fn swap_erc20_to_icrc(recipient: Account, amount: PicoEkoke) -> EkokeResult<()> {
SwapPool::withdraw(recipient, amount).await
#[allow(dead_code)]
pub async fn swap_erc20_to_icrc() -> EkokeResult<()> {
let rpc_client = EthRpcClient::new(Configuration::get_eth_network());
// get ekoke swapped events
let from_block = ERC20_LOGS_START_BLOCK.with(|cell| *cell.borrow().get());
let (last_block, events) = rpc_client.get_ekoke_swapped_events(from_block).await?;

// update last block
ERC20_LOGS_START_BLOCK
.with(|cell| cell.borrow_mut().set(last_block + 1))
.unwrap();

// withdraw to recipient
for event in events {
match (event.principal(), event.amount()) {
(Ok(principal), Ok(amount)) => {
SwapPool::withdraw(Account::from(principal), amount.into()).await?;
}
_ => continue,
}
}

Ok(())
}

/// Returns the swap fee.
Expand All @@ -81,6 +120,9 @@ impl Erc20Bridge {
}

/// Fetches the current gas price from etherscan
///
/// Used only in wasm32
#[allow(dead_code)]
pub async fn fetch_gas_price() -> EkokeResult<()> {
if !SwapFee::should_update_gas_price() {
return Ok(());
Expand Down
12 changes: 6 additions & 6 deletions src/ekoke/src/app/erc20_bridge/cketh_withdrawal.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use candid::{CandidType, Nat, Principal};
use did::{
ekoke::{EkokeError, EkokeResult},
H160,
};
use icrc::{icrc1::account::Account, IcrcLedgerClient};
use did::ekoke::{EkokeError, EkokeResult};
use did::H160;
use icrc::icrc1::account::Account;
use icrc::IcrcLedgerClient;
use serde::Deserialize;

use crate::{app::configuration::Configuration, constants::ETH_MIN_WITHDRAWAL_AMOUNT};
use crate::app::configuration::Configuration;
use crate::constants::ETH_MIN_WITHDRAWAL_AMOUNT;

pub struct CkEthWithdrawal;

Expand Down
Loading

0 comments on commit d438452

Please sign in to comment.