Skip to content
Open
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
9 changes: 9 additions & 0 deletions rs/ethereum/cketh/minter/cketh_minter.did
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ type InitArg = record {
// with the Ethereum blockchain. If not specified, uses the production or
// staging EVM RPC canister based on the ethereum_network field.
evm_rpc_id : opt principal;

// Address of the sweeper smart contract.
ethereum_sweeper_contract_address : opt text;
};

type UpgradeArg = record {
Expand Down Expand Up @@ -143,6 +146,9 @@ type UpgradeArg = record {

// Change the last scraped block number of the deposit with subaccount helper smart contract.
last_deposit_with_subaccount_scraped_block_number : opt nat;

// Change the sweeper smart contract address.
ethereum_sweeper_contract_address : opt text;
};

type MinterArg = variant { UpgradeArg : UpgradeArg; InitArg : InitArg };
Expand Down Expand Up @@ -202,6 +208,9 @@ type MinterInfo = record {
// Address of the ETH or ERC20 deposit with subaccount helper smart contract.
deposit_with_subaccount_helper_contract_address: opt text;

// Address of the sweeper smart contract.
sweeper_contract_address: opt text;

// Information of supported ERC20 tokens.
supported_ckerc20_tokens: opt vec CkErc20Token;

Expand Down
2 changes: 2 additions & 0 deletions rs/ethereum/cketh/minter/src/dashboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ pub struct DashboardTemplate {
pub ethereum_network: EthereumNetwork,
pub ecdsa_key_name: String,
pub minter_address: String,
pub sweeper_contract_address: Option<Address>,
pub log_scrapings: LogScrapings,
pub next_transaction_nonce: TransactionNonce,
pub minimum_withdrawal_amount: Wei,
Expand Down Expand Up @@ -482,6 +483,7 @@ impl DashboardTemplate {
.minter_address()
.map(|addr| addr.to_string())
.unwrap_or_default(),
sweeper_contract_address: state.sweeper_contract_address,
log_scrapings: state.log_scrapings.clone(),
cketh_ledger_id: state.cketh_ledger_id,
next_transaction_nonce: state.eth_transactions.next_transaction_nonce(),
Expand Down
25 changes: 22 additions & 3 deletions rs/ethereum/cketh/minter/src/dashboard/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,18 @@ fn should_display_metadata() {
.has_minimum_withdrawal_amount("10_000_000_000_000_000")
.has_eth_balance("0")
.has_total_effective_tx_fees("0")
.has_total_unspent_tx_fees("0");
.has_total_unspent_tx_fees("0")
.has_no_elements_matching("#sweeper-contract-address");

let dashboard = DashboardTemplate {
sweeper_contract_address: Some(
Address::from_str("0x2D39863d30716aaf2B7fFFd85Dd03Dda2BFC2E38").unwrap(),
),
..dashboard
};

DashboardAssert::assert_that(dashboard)
.has_sweeper_contract_address("0x2D39863d30716aaf2B7fFFd85Dd03Dda2BFC2E38");
}

#[test]
Expand Down Expand Up @@ -147,8 +158,7 @@ fn should_display_helper_smart_contracts() {
) {
dashboard
.log_scrapings
.set_contract_address(id, contract_address.parse().unwrap())
.unwrap();
.set_contract_address(id, contract_address.parse().unwrap());
dashboard
.log_scrapings
.set_last_scraped_block_number(id, BlockNumber::from(last_scraped_block_number));
Expand Down Expand Up @@ -1146,6 +1156,7 @@ fn initial_state() -> State {
next_transaction_nonce: TransactionNonce::ZERO.into(),
last_scraped_block_number: candid::Nat::from(INITIAL_LAST_SCRAPED_BLOCK_NUMBER),
evm_rpc_id: None,
ethereum_sweeper_contract_address: None,
})
.expect("valid init args")
}
Expand Down Expand Up @@ -1611,6 +1622,14 @@ mod assertions {
)
}

pub fn has_sweeper_contract_address(&self, expected_address: &str) -> &Self {
self.has_string_value(
"#sweeper-contract-address > td",
expected_address,
"wrong sweeper contract address",
)
}

pub fn has_helper_contract(
&self,
id: LogScrapingId,
Expand Down
1 change: 1 addition & 0 deletions rs/ethereum/cketh/minter/src/endpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ pub struct MinterInfo {
pub eth_helper_contract_address: Option<String>,
pub erc20_helper_contract_address: Option<String>,
pub deposit_with_subaccount_helper_contract_address: Option<String>,
pub sweeper_contract_address: Option<String>,
pub supported_ckerc20_tokens: Option<Vec<CkErc20Token>>,
pub minimum_withdrawal_amount: Option<Nat>,
pub ethereum_block_height: Option<CandidBlockTag>,
Expand Down
11 changes: 4 additions & 7 deletions rs/ethereum/cketh/minter/src/eth_logs/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,13 +277,10 @@ mod scraping {
let last_scraped_block_number = BlockNumber::from(6_970_446_u32);
let state = {
let mut state = initial_state();
state
.log_scrapings
.set_contract_address(
LogScrapingId::EthOrErc20DepositWithSubaccount,
CONTRACT_ADDRESS,
)
.unwrap();
state.log_scrapings.set_contract_address(
LogScrapingId::EthOrErc20DepositWithSubaccount,
CONTRACT_ADDRESS,
);
state.log_scrapings.set_last_scraped_block_number(
LogScrapingId::EthOrErc20DepositWithSubaccount,
last_scraped_block_number,
Expand Down
17 changes: 10 additions & 7 deletions rs/ethereum/cketh/minter/src/lifecycle/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ pub struct InitArg {
pub last_scraped_block_number: Nat,
#[cbor(n(9), with = "icrc_cbor::principal::option")]
pub evm_rpc_id: Option<Principal>,
#[n(10)]
pub ethereum_sweeper_contract_address: Option<String>,
}

impl TryFrom<InitArg> for State {
Expand All @@ -47,6 +49,7 @@ impl TryFrom<InitArg> for State {
next_transaction_nonce,
last_scraped_block_number,
evm_rpc_id,
ethereum_sweeper_contract_address,
}: InitArg,
) -> Result<Self, Self::Error> {
use std::str::FromStr;
Expand All @@ -59,9 +62,11 @@ impl TryFrom<InitArg> for State {
let eth_helper_contract_address = ethereum_contract_address
.map(|a| Address::from_str(&a))
.transpose()
.map_err(|e| {
InvalidStateError::InvalidEthereumContractAddress(format!("ERROR: {e}"))
})?;
.map_err(|e| InvalidStateError::InvalidContractAddress(format!("ERROR: {e}")))?;
let sweeper_contract_address = ethereum_sweeper_contract_address
.map(|a| Address::from_str(&a))
.transpose()
.map_err(|e| InvalidStateError::InvalidContractAddress(format!("ERROR: {e}")))?;
let last_scraped_block_number = BlockNumber::try_from(last_scraped_block_number)
.map_err(|e| InvalidStateError::InvalidLastScrapedBlockNumber(format!("ERROR: {e}")))?;
let first_scraped_block_number =
Expand All @@ -79,10 +84,7 @@ impl TryFrom<InitArg> for State {
let mut log_scrapings = LogScrapings::new(last_scraped_block_number);
if let Some(contract_address) = eth_helper_contract_address {
log_scrapings
.set_contract_address(LogScrapingId::EthDepositWithoutSubaccount, contract_address)
.map_err(|e| {
InvalidStateError::InvalidEthereumContractAddress(format!("ERROR: {e:?}"))
})?;
.set_contract_address(LogScrapingId::EthDepositWithoutSubaccount, contract_address);
}
let state = Self {
ethereum_network,
Expand Down Expand Up @@ -110,6 +112,7 @@ impl TryFrom<InitArg> for State {
erc20_balances: Default::default(),
log_scrapings,
automatic_deposits: AutomaticDeposits::default(),
sweeper_contract_address,
};
state.validate_config()?;
Ok(state)
Expand Down
48 changes: 45 additions & 3 deletions rs/ethereum/cketh/minter/src/lifecycle/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ mod init {
use crate::test_fixtures::valid_init_arg;
use assert_matches::assert_matches;
use candid::{Nat, Principal};
use ic_ethereum_types::Address;
use num_bigint::BigUint;
use std::str::FromStr;

#[test]
fn should_fail_when_init_args_invalid() {
Expand All @@ -31,7 +33,7 @@ mod init {
ethereum_contract_address: Some("invalid".to_string()),
..valid_init_arg()
}),
Err(InvalidStateError::InvalidEthereumContractAddress(_))
Err(InvalidStateError::InvalidContractAddress(_))
);

assert_matches!(
Expand All @@ -41,7 +43,38 @@ mod init {
),
..valid_init_arg()
}),
Err(InvalidStateError::InvalidEthereumContractAddress(_))
Err(InvalidStateError::InvalidContractAddress(_))
);

assert_matches!(
State::try_from(InitArg {
ethereum_sweeper_contract_address: Some("invalid".to_string()),
..valid_init_arg()
}),
Err(InvalidStateError::InvalidContractAddress(_))
);

assert_matches!(
State::try_from(InitArg {
ethereum_sweeper_contract_address: Some(
"0x0000000000000000000000000000000000000000".to_string(),
),
..valid_init_arg()
}),
Err(InvalidStateError::InvalidContractAddress(_))
);

assert_matches!(
State::try_from(InitArg {
ethereum_contract_address: Some(
"0xb44B5e756A894775FC32EDdf3314Bb1B1944dC34".to_string(),
),
ethereum_sweeper_contract_address: Some(
"0xb44B5e756A894775FC32EDdf3314Bb1B1944dC34".to_string(),
),
..valid_init_arg()
}),
Err(InvalidStateError::InvalidContractAddress(_))
);

assert_matches!(
Expand Down Expand Up @@ -75,7 +108,12 @@ mod init {

#[test]
fn should_succeed() {
let init_arg = valid_init_arg();
let init_arg = InitArg {
ethereum_sweeper_contract_address: Some(
"0xb44B5e756A894775FC32EDdf3314Bb1B1944dC34".to_string(),
),
..valid_init_arg()
};

let state = State::try_from(init_arg.clone()).expect("valid init args");

Expand All @@ -96,5 +134,9 @@ mod init {
state.eth_transactions.next_transaction_nonce(),
TransactionNonce::ZERO
);
assert_eq!(
state.sweeper_contract_address,
Some(Address::from_str("0xb44B5e756A894775FC32EDdf3314Bb1B1944dC34").unwrap())
);
}
}
2 changes: 2 additions & 0 deletions rs/ethereum/cketh/minter/src/lifecycle/upgrade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ pub struct UpgradeArg {
pub deposit_with_subaccount_helper_contract_address: Option<String>,
#[cbor(n(9), with = "icrc_cbor::nat::option")]
pub last_deposit_with_subaccount_scraped_block_number: Option<Nat>,
#[n(10)]
pub ethereum_sweeper_contract_address: Option<String>,
}

pub fn post_upgrade(upgrade_args: Option<UpgradeArg>) {
Expand Down
1 change: 1 addition & 0 deletions rs/ethereum/cketh/minter/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ async fn get_minter_info() -> MinterInfo {
eth_helper_contract_address,
erc20_helper_contract_address,
deposit_with_subaccount_helper_contract_address,
sweeper_contract_address: s.sweeper_contract_address.map(|a| a.to_string()),
supported_ckerc20_tokens,
minimum_withdrawal_amount: Some(s.cketh_minimum_withdrawal_amount.into()),
ethereum_block_height: Some(s.ethereum_block_height.clone()),
Expand Down
Loading
Loading