Skip to content

Commit

Permalink
Add gnosis gas oracle (#309)
Browse files Browse the repository at this point in the history
Co-authored-by: Seun Lanlege <[email protected]>
  • Loading branch information
Wizdave97 and seunlanlege authored Sep 16, 2024
1 parent 06ebda6 commit c1c436d
Show file tree
Hide file tree
Showing 12 changed files with 483 additions and 157 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -334,9 +334,9 @@ jobs:
# run: |
# cargo test -p ismp-solidity-tests -- --nocapture --ignored

- name: parachain messaging relayer integration tests
run: |
cargo test -p tesseract-integration-test --lib -- --ignored --test-threads=1
# - name: parachain messaging relayer integration tests
# run: |
# cargo test -p tesseract-integration-test --lib -- --ignored --test-threads=1

- name: Xcm integration tests
run: |
Expand Down
4 changes: 2 additions & 2 deletions evm/abi/src/generated/erc20.rs

Large diffs are not rendered by default.

57 changes: 0 additions & 57 deletions evm/abi/src/generated/evm_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5649,63 +5649,6 @@ pub mod evm_host {
Hash,
)]
pub struct VetoesReturn(pub ::ethers::core::types::Address);
///`DispatchGet(bytes,uint64,bytes[],uint64,uint256,bytes)`
#[derive(
Clone,
::ethers::contract::EthAbiType,
::ethers::contract::EthAbiCodec,
Default,
Debug,
PartialEq,
Eq,
Hash,
)]
pub struct DispatchGet {
pub dest: ::ethers::core::types::Bytes,
pub height: u64,
pub keys: ::std::vec::Vec<::ethers::core::types::Bytes>,
pub timeout: u64,
pub fee: ::ethers::core::types::U256,
pub context: ::ethers::core::types::Bytes,
}
///`DispatchPost(bytes,bytes,bytes,uint64,uint256,address)`
#[derive(
Clone,
::ethers::contract::EthAbiType,
::ethers::contract::EthAbiCodec,
Default,
Debug,
PartialEq,
Eq,
Hash,
)]
pub struct DispatchPost {
pub dest: ::ethers::core::types::Bytes,
pub to: ::ethers::core::types::Bytes,
pub body: ::ethers::core::types::Bytes,
pub timeout: u64,
pub fee: ::ethers::core::types::U256,
pub payer: ::ethers::core::types::Address,
}
///`DispatchPostResponse((bytes,bytes,uint64,bytes,bytes,uint64,bytes),bytes,uint64,uint256,
/// address)`
#[derive(
Clone,
::ethers::contract::EthAbiType,
::ethers::contract::EthAbiCodec,
Default,
Debug,
PartialEq,
Eq,
Hash,
)]
pub struct DispatchPostResponse {
pub request: PostRequest,
pub response: ::ethers::core::types::Bytes,
pub timeout: u64,
pub fee: ::ethers::core::types::U256,
pub payer: ::ethers::core::types::Address,
}
///`FeeMetadata(uint256,address)`
#[derive(
Clone,
Expand Down
406 changes: 340 additions & 66 deletions evm/abi/src/generated/host_manager.rs

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions evm/abi/src/generated/ping_module.rs

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions evm/abi/src/generated/shared_types.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,60 @@
///`DispatchGet(bytes,uint64,bytes[],uint64,uint256,bytes)`
#[derive(
Clone,
::ethers::contract::EthAbiType,
::ethers::contract::EthAbiCodec,
Default,
Debug,
PartialEq,
Eq,
Hash,
)]
pub struct DispatchGet {
pub dest: ::ethers::core::types::Bytes,
pub height: u64,
pub keys: ::std::vec::Vec<::ethers::core::types::Bytes>,
pub timeout: u64,
pub fee: ::ethers::core::types::U256,
pub context: ::ethers::core::types::Bytes,
}
///`DispatchPost(bytes,bytes,bytes,uint64,uint256,address)`
#[derive(
Clone,
::ethers::contract::EthAbiType,
::ethers::contract::EthAbiCodec,
Default,
Debug,
PartialEq,
Eq,
Hash,
)]
pub struct DispatchPost {
pub dest: ::ethers::core::types::Bytes,
pub to: ::ethers::core::types::Bytes,
pub body: ::ethers::core::types::Bytes,
pub timeout: u64,
pub fee: ::ethers::core::types::U256,
pub payer: ::ethers::core::types::Address,
}
///`DispatchPostResponse((bytes,bytes,uint64,bytes,bytes,uint64,bytes),bytes,uint64,uint256,
/// address)`
#[derive(
Clone,
::ethers::contract::EthAbiType,
::ethers::contract::EthAbiCodec,
Default,
Debug,
PartialEq,
Eq,
Hash,
)]
pub struct DispatchPostResponse {
pub request: PostRequest,
pub response: ::ethers::core::types::Bytes,
pub timeout: u64,
pub fee: ::ethers::core::types::U256,
pub payer: ::ethers::core::types::Address,
}
///`GetRequest(bytes,bytes,uint64,address,uint64,bytes[],uint64,bytes)`
#[derive(
Clone,
Expand Down
2 changes: 1 addition & 1 deletion modules/hyperclient/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@polytope-labs/hyperclient",
"description": "The hyperclient is a library for managing (in-flight) ISMP requests",
"version": "0.5.0",
"version": "0.5.2",
"author": "Polytope Labs ([email protected])",
"license": "Apache-2.0",
"bugs": {
Expand Down
16 changes: 8 additions & 8 deletions modules/hyperclient/src/internals/post_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub async fn query_post_request_status_internal(
}

// Checking to see if the messaging has timed-out
if destination_current_timestamp.as_secs() >= post.timeout_timestamp {
if destination_current_timestamp.as_secs() >= post.timeout().as_secs() {
// request timed out before reaching the destination chain
return Ok(MessageStatusWithMetadata::Timeout);
}
Expand All @@ -87,7 +87,7 @@ pub async fn query_post_request_status_internal(
return Ok(MessageStatusWithMetadata::HyperbridgeDelivered { meta: Default::default() });
}

if hyperbridge_current_timestamp.as_secs() > post.timeout_timestamp {
if hyperbridge_current_timestamp.as_secs() > post.timeout().as_secs() {
// the request timed out before getting to hyper bridge
return Ok(MessageStatusWithMetadata::Timeout);
}
Expand Down Expand Up @@ -217,7 +217,7 @@ pub async fn post_request_status_stream(
)));
}

if destination_current_timestamp.as_secs() >= post.timeout_timestamp {
if destination_current_timestamp.as_secs() >= post.timeout().as_secs() {
// Checking to see if the message has timed-out
return Ok(Some((
Ok(MessageStatusWithMetadata::Timeout),
Expand All @@ -244,7 +244,7 @@ pub async fn post_request_status_stream(
)));
}

if hyperbridge_current_timestamp.as_secs() >= post.timeout_timestamp {
if hyperbridge_current_timestamp.as_secs() >= post.timeout().as_secs() {
// Checking to see if the message has timed-out
return Ok(Some((
Ok(MessageStatusWithMetadata::Timeout),
Expand Down Expand Up @@ -660,7 +660,7 @@ pub async fn timeout_post_request_stream(
let source_client = source_client.clone();
let req = Request::Post(post.clone());
let hash = hash_request::<Keccak256>(&req);

let post = post.clone();
async move {
let lambda = || async {
match state {
Expand All @@ -678,7 +678,7 @@ pub async fn timeout_post_request_stream(
})
.await?;

if state_commitment.timestamp > post.timeout_timestamp {
if state_commitment.timestamp > post.timeout().as_secs() {
// early return if the destination has already finalized the height
return Ok(Some((
Ok(TimeoutStatus::DestinationFinalized {
Expand All @@ -702,7 +702,7 @@ pub async fn timeout_post_request_stream(
let commitment = hyperbridge_client
.query_state_machine_commitment(state_machine_height)
.await?;
if commitment.timestamp > post.timeout_timestamp {
if commitment.timestamp > post.timeout().as_secs() {
valid_proof_height = Some(ev);
break;
}
Expand Down Expand Up @@ -813,7 +813,7 @@ pub async fn timeout_post_request_stream(
let commitment = source_client
.query_state_machine_commitment(state_machine_height)
.await?;
if commitment.timestamp > post.timeout_timestamp &&
if commitment.timestamp > post.timeout().as_secs() &&
ev.event.latest_height >= hyperbridge_height
{
valid_proof_height = Some(ev);
Expand Down
12 changes: 12 additions & 0 deletions modules/ismp/core/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ pub struct PostRequest {
pub body: Vec<u8>,
}

impl PostRequest {
/// Returns the timeout timestamp for a request
pub fn timeout(&self) -> Duration {
get_timeout(self.timeout_timestamp)
}

/// Returns true if the destination chain timestamp has exceeded the request timeout timestamp
pub fn timed_out(&self, proof_timestamp: Duration) -> bool {
proof_timestamp >= self.timeout()
}
}

impl core::fmt::Display for PostRequest {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
writeln!(f, "Post {{")?;
Expand Down
54 changes: 45 additions & 9 deletions tesseract/evm/src/gas_oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pub struct GasBreakdown {
/// Function gets current gas price (for execution) in wei and return the equivalent in USD,
pub async fn get_current_gas_cost_in_usd(
chain: StateMachine,
api_keys: &String,
api_keys: &str,
client: Arc<Provider<Http>>,
gas_price_buffer: Option<u32>,
) -> Result<GasBreakdown, Error> {
Expand Down Expand Up @@ -166,11 +166,27 @@ pub async fn get_current_gas_cost_in_usd(
};
},
CHIADO_CHAIN_ID | GNOSIS_CHAIN_ID => {
// temporarily use naive gas price for gnosis
gas_price = client.get_gas_price().await?;
// one unit of the gas token is 1 usd
unit_wei = get_cost_of_one_wei(U256::one());
gas_price_cost = convert_27_decimals_to_18_decimals(unit_wei * gas_price)?;
let node_gas_price: U256 = client.get_gas_price().await?;
#[derive(Debug, Deserialize, Clone)]
struct BlockscoutResponse {
average: f32,
}
if CHIADO_CHAIN_ID == inner_evm {
let uri = "https://blockscout.chiadochain.net/api/v1/gas-price-oracle";
let response_json =
make_request::<BlockscoutResponse>(&uri, Default::default()).await?;
let oracle_gas_price = parse_units(response_json.average, "gwei")?.into();
gas_price = std::cmp::max(node_gas_price, oracle_gas_price);
} else {
let uri = "https://blockscout.com/xdai/mainnet/api/v1/gas-price-oracle";
let response_json =
make_request::<BlockscoutResponse>(&uri, Default::default()).await?;
let oracle_gas_price = parse_units(response_json.average, "gwei")?.into();
gas_price = std::cmp::max(node_gas_price, oracle_gas_price);
}
// Gnosis uses a stable coin for gas token which means the usd is
// equivalent to the gas price
gas_price_cost = gas_price
},
POLYGON_CHAIN_ID | POLYGON_TESTNET_CHAIN_ID => {
let uri = format!(
Expand Down Expand Up @@ -243,8 +259,7 @@ pub async fn get_current_gas_cost_in_usd(
let response_json =
make_request::<GasResponse>(&uri, Default::default()).await?;
let oracle_gas_price =
parse_units(response_json.result.safe_gas_price.to_string(), "gwei")?
.into();
parse_units(response_json.result.safe_gas_price, "gwei")?.into();
gas_price = std::cmp::max(node_gas_price, oracle_gas_price);
let eth_usd = parse_to_27_decimals(&response_json.result.usd_price)?;
unit_wei = get_cost_of_one_wei(eth_usd);
Expand Down Expand Up @@ -386,7 +401,7 @@ mod test {
use crate::gas_oracle::{
convert_27_decimals_to_18_decimals, get_cost_of_one_wei, get_current_gas_cost_in_usd,
get_l2_data_cost, parse_to_27_decimals, ARBITRUM_SEPOLIA_CHAIN_ID, BSC_TESTNET_CHAIN_ID,
OPTIMISM_SEPOLIA_CHAIN_ID, POLYGON_TESTNET_CHAIN_ID, SEPOLIA_CHAIN_ID,
GNOSIS_CHAIN_ID, OPTIMISM_SEPOLIA_CHAIN_ID, POLYGON_TESTNET_CHAIN_ID, SEPOLIA_CHAIN_ID,
};
use ethers::{prelude::Provider, providers::Http, utils::parse_units};
use ismp::host::StateMachine;
Expand Down Expand Up @@ -462,6 +477,27 @@ mod test {
println!("Ethereum Gas Cost Polygon Mainnet: {:?}", ethereum_gas_cost_in_usd);
}

#[tokio::test]
#[ignore]
async fn get_gas_price_gnosis_testnet() {
dotenv::dotenv().ok();
let ethereum_rpc_uri = std::env::var("CHIADO_URL").expect("get url is not set in .env.");
// Client is unused in this test
let provider = Provider::<Http>::try_from(ethereum_rpc_uri).unwrap();
let client = Arc::new(provider.clone());

let ethereum_gas_cost_in_usd = get_current_gas_cost_in_usd(
StateMachine::Evm(GNOSIS_CHAIN_ID),
"",
client.clone(),
None,
)
.await
.unwrap();

println!("Ethereum Gas Cost Gnosis Mainnet: {:?}", ethereum_gas_cost_in_usd);
}

#[tokio::test]
#[ignore]
async fn get_gas_price_polygon_testnet() {
Expand Down
19 changes: 11 additions & 8 deletions tesseract/evm/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,19 +453,20 @@ impl IsmpProvider for EvmClient {
};

let gas_cost_for_data_in_usd = match client.state_machine {
StateMachine::Evm(_) =>
StateMachine::Evm(_) => {
get_l2_data_cost(
call.tx.rlp(),
client.state_machine,
client.client.clone(),
gas_breakdown.unit_wei_cost,
)
.await?,
.await?
},
_ => U256::zero().into(),
};

let execution_cost = (gas_breakdown.gas_price_cost * gas_to_be_used) +
gas_cost_for_data_in_usd;
let execution_cost = (gas_breakdown.gas_price_cost * gas_to_be_used)
+ gas_cost_for_data_in_usd;
Ok::<_, Error>(EstimateGasReturnParams {
execution_cost,
successful_execution,
Expand Down Expand Up @@ -727,7 +728,7 @@ impl IsmpProvider for EvmClient {
let mut results = vec![];
for msg in messages {
match msg {
Message::Request(req_msg) =>
Message::Request(req_msg) => {
for post in req_msg.requests {
let req = Request::Post(post);
let commitment = hash_request::<Hasher>(&req);
Expand All @@ -744,11 +745,12 @@ impl IsmpProvider for EvmClient {

results.push(tx_receipt);
}
},
}
},
Message::Response(ResponseMessage {
datagram: RequestResponse::Response(resp),
..
}) =>
}) => {
for res in resp {
let commitment = hash_response::<Hasher>(&res);
let request_commitment = hash_request::<Hasher>(&res.request());
Expand All @@ -766,7 +768,8 @@ impl IsmpProvider for EvmClient {

results.push(tx_receipt);
}
},
}
},
_ => {},
}
}
Expand Down
Loading

0 comments on commit c1c436d

Please sign in to comment.