feature: adds XAppConnectionManager interface (#273)
parent
d3788f0457
commit
03fa9bcded
@ -0,0 +1,338 @@ |
||||
[ |
||||
{ |
||||
"inputs": [], |
||||
"stateMutability": "nonpayable", |
||||
"type": "constructor" |
||||
}, |
||||
{ |
||||
"anonymous": false, |
||||
"inputs": [ |
||||
{ |
||||
"indexed": true, |
||||
"internalType": "address", |
||||
"name": "previousOwner", |
||||
"type": "address" |
||||
}, |
||||
{ |
||||
"indexed": true, |
||||
"internalType": "address", |
||||
"name": "newOwner", |
||||
"type": "address" |
||||
} |
||||
], |
||||
"name": "OwnershipTransferred", |
||||
"type": "event" |
||||
}, |
||||
{ |
||||
"anonymous": false, |
||||
"inputs": [ |
||||
{ |
||||
"indexed": true, |
||||
"internalType": "uint32", |
||||
"name": "domain", |
||||
"type": "uint32" |
||||
}, |
||||
{ |
||||
"indexed": false, |
||||
"internalType": "address", |
||||
"name": "replica", |
||||
"type": "address" |
||||
} |
||||
], |
||||
"name": "ReplicaEnrolled", |
||||
"type": "event" |
||||
}, |
||||
{ |
||||
"anonymous": false, |
||||
"inputs": [ |
||||
{ |
||||
"indexed": true, |
||||
"internalType": "uint32", |
||||
"name": "domain", |
||||
"type": "uint32" |
||||
}, |
||||
{ |
||||
"indexed": false, |
||||
"internalType": "address", |
||||
"name": "replica", |
||||
"type": "address" |
||||
} |
||||
], |
||||
"name": "ReplicaUnenrolled", |
||||
"type": "event" |
||||
}, |
||||
{ |
||||
"anonymous": false, |
||||
"inputs": [ |
||||
{ |
||||
"indexed": true, |
||||
"internalType": "uint32", |
||||
"name": "domain", |
||||
"type": "uint32" |
||||
}, |
||||
{ |
||||
"indexed": false, |
||||
"internalType": "address", |
||||
"name": "watcher", |
||||
"type": "address" |
||||
}, |
||||
{ |
||||
"indexed": false, |
||||
"internalType": "bool", |
||||
"name": "access", |
||||
"type": "bool" |
||||
} |
||||
], |
||||
"name": "WatcherPermissionSet", |
||||
"type": "event" |
||||
}, |
||||
{ |
||||
"inputs": [ |
||||
{ |
||||
"internalType": "uint32", |
||||
"name": "", |
||||
"type": "uint32" |
||||
} |
||||
], |
||||
"name": "domainToReplica", |
||||
"outputs": [ |
||||
{ |
||||
"internalType": "address", |
||||
"name": "", |
||||
"type": "address" |
||||
} |
||||
], |
||||
"stateMutability": "view", |
||||
"type": "function" |
||||
}, |
||||
{ |
||||
"inputs": [], |
||||
"name": "home", |
||||
"outputs": [ |
||||
{ |
||||
"internalType": "contract Home", |
||||
"name": "", |
||||
"type": "address" |
||||
} |
||||
], |
||||
"stateMutability": "view", |
||||
"type": "function" |
||||
}, |
||||
{ |
||||
"inputs": [ |
||||
{ |
||||
"internalType": "address", |
||||
"name": "_owner", |
||||
"type": "address" |
||||
} |
||||
], |
||||
"name": "isOwner", |
||||
"outputs": [ |
||||
{ |
||||
"internalType": "bool", |
||||
"name": "", |
||||
"type": "bool" |
||||
} |
||||
], |
||||
"stateMutability": "view", |
||||
"type": "function" |
||||
}, |
||||
{ |
||||
"inputs": [ |
||||
{ |
||||
"internalType": "address", |
||||
"name": "_replica", |
||||
"type": "address" |
||||
} |
||||
], |
||||
"name": "isReplica", |
||||
"outputs": [ |
||||
{ |
||||
"internalType": "bool", |
||||
"name": "", |
||||
"type": "bool" |
||||
} |
||||
], |
||||
"stateMutability": "view", |
||||
"type": "function" |
||||
}, |
||||
{ |
||||
"inputs": [], |
||||
"name": "originDomain", |
||||
"outputs": [ |
||||
{ |
||||
"internalType": "uint32", |
||||
"name": "", |
||||
"type": "uint32" |
||||
} |
||||
], |
||||
"stateMutability": "view", |
||||
"type": "function" |
||||
}, |
||||
{ |
||||
"inputs": [], |
||||
"name": "owner", |
||||
"outputs": [ |
||||
{ |
||||
"internalType": "address", |
||||
"name": "", |
||||
"type": "address" |
||||
} |
||||
], |
||||
"stateMutability": "view", |
||||
"type": "function" |
||||
}, |
||||
{ |
||||
"inputs": [ |
||||
{ |
||||
"internalType": "address", |
||||
"name": "_replica", |
||||
"type": "address" |
||||
}, |
||||
{ |
||||
"internalType": "uint32", |
||||
"name": "_domain", |
||||
"type": "uint32" |
||||
} |
||||
], |
||||
"name": "ownerEnrollReplica", |
||||
"outputs": [], |
||||
"stateMutability": "nonpayable", |
||||
"type": "function" |
||||
}, |
||||
{ |
||||
"inputs": [ |
||||
{ |
||||
"internalType": "address", |
||||
"name": "_replica", |
||||
"type": "address" |
||||
} |
||||
], |
||||
"name": "ownerUnenrollReplica", |
||||
"outputs": [], |
||||
"stateMutability": "nonpayable", |
||||
"type": "function" |
||||
}, |
||||
{ |
||||
"inputs": [], |
||||
"name": "renounceOwnership", |
||||
"outputs": [], |
||||
"stateMutability": "nonpayable", |
||||
"type": "function" |
||||
}, |
||||
{ |
||||
"inputs": [ |
||||
{ |
||||
"internalType": "address", |
||||
"name": "", |
||||
"type": "address" |
||||
} |
||||
], |
||||
"name": "replicaToDomain", |
||||
"outputs": [ |
||||
{ |
||||
"internalType": "uint32", |
||||
"name": "", |
||||
"type": "uint32" |
||||
} |
||||
], |
||||
"stateMutability": "view", |
||||
"type": "function" |
||||
}, |
||||
{ |
||||
"inputs": [ |
||||
{ |
||||
"internalType": "address", |
||||
"name": "_home", |
||||
"type": "address" |
||||
} |
||||
], |
||||
"name": "setHome", |
||||
"outputs": [], |
||||
"stateMutability": "nonpayable", |
||||
"type": "function" |
||||
}, |
||||
{ |
||||
"inputs": [ |
||||
{ |
||||
"internalType": "address", |
||||
"name": "_watcher", |
||||
"type": "address" |
||||
}, |
||||
{ |
||||
"internalType": "uint32", |
||||
"name": "_domain", |
||||
"type": "uint32" |
||||
}, |
||||
{ |
||||
"internalType": "bool", |
||||
"name": "_access", |
||||
"type": "bool" |
||||
} |
||||
], |
||||
"name": "setWatcherPermission", |
||||
"outputs": [], |
||||
"stateMutability": "nonpayable", |
||||
"type": "function" |
||||
}, |
||||
{ |
||||
"inputs": [ |
||||
{ |
||||
"internalType": "address", |
||||
"name": "newOwner", |
||||
"type": "address" |
||||
} |
||||
], |
||||
"name": "transferOwnership", |
||||
"outputs": [], |
||||
"stateMutability": "nonpayable", |
||||
"type": "function" |
||||
}, |
||||
{ |
||||
"inputs": [ |
||||
{ |
||||
"internalType": "uint32", |
||||
"name": "_domain", |
||||
"type": "uint32" |
||||
}, |
||||
{ |
||||
"internalType": "address", |
||||
"name": "_updater", |
||||
"type": "address" |
||||
}, |
||||
{ |
||||
"internalType": "bytes", |
||||
"name": "_signature", |
||||
"type": "bytes" |
||||
} |
||||
], |
||||
"name": "unenrollReplica", |
||||
"outputs": [], |
||||
"stateMutability": "nonpayable", |
||||
"type": "function" |
||||
}, |
||||
{ |
||||
"inputs": [ |
||||
{ |
||||
"internalType": "address", |
||||
"name": "_watcher", |
||||
"type": "address" |
||||
}, |
||||
{ |
||||
"internalType": "uint32", |
||||
"name": "_domain", |
||||
"type": "uint32" |
||||
} |
||||
], |
||||
"name": "watcherPermission", |
||||
"outputs": [ |
||||
{ |
||||
"internalType": "bool", |
||||
"name": "", |
||||
"type": "bool" |
||||
} |
||||
], |
||||
"stateMutability": "view", |
||||
"type": "function" |
||||
} |
||||
] |
@ -0,0 +1,56 @@ |
||||
use crate::{ |
||||
traits::{ChainCommunicationError, TxOutcome}, |
||||
OpticsIdentifier, SignedFailureNotification, |
||||
}; |
||||
use async_trait::async_trait; |
||||
|
||||
/// Interface for on-chain XAppConnectionManager
|
||||
#[async_trait] |
||||
pub trait ConnectionManager: Send + Sync + std::fmt::Debug { |
||||
/// Return the contract's local domain ID
|
||||
fn local_domain(&self) -> u32; |
||||
|
||||
/// Return true if provided address is the contract's owner
|
||||
async fn is_owner(&self, address: OpticsIdentifier) -> Result<bool, ChainCommunicationError>; |
||||
|
||||
/// Returns true if provided address is enrolled replica
|
||||
async fn is_replica(&self, address: OpticsIdentifier) -> Result<bool, ChainCommunicationError>; |
||||
|
||||
/// Returns permission for address at given domain
|
||||
async fn watcher_permission( |
||||
&self, |
||||
address: OpticsIdentifier, |
||||
domain: u32, |
||||
) -> Result<bool, ChainCommunicationError>; |
||||
|
||||
/// onlyOwner function. Enrolls replica at given domain chain.
|
||||
async fn owner_enroll_replica( |
||||
&self, |
||||
replica: OpticsIdentifier, |
||||
domain: u32, |
||||
) -> Result<TxOutcome, ChainCommunicationError>; |
||||
|
||||
/// onlyOwner function. Unenrolls replica.
|
||||
async fn owner_unenroll_replica( |
||||
&self, |
||||
replica: OpticsIdentifier, |
||||
) -> Result<TxOutcome, ChainCommunicationError>; |
||||
|
||||
/// onlyOwner function. Sets contract's home to provided home.
|
||||
async fn set_home(&self, home: OpticsIdentifier) -> Result<TxOutcome, ChainCommunicationError>; |
||||
|
||||
/// onlyOwner function. Sets permission for watcher at given domain.
|
||||
async fn set_watcher_permission( |
||||
&self, |
||||
watcher: OpticsIdentifier, |
||||
domain: u32, |
||||
access: bool, |
||||
) -> Result<TxOutcome, ChainCommunicationError>; |
||||
|
||||
/// Unenroll the replica at the given domain provided an updater address
|
||||
/// and `SignedFailureNotification` from a watcher
|
||||
async fn unenroll_replica( |
||||
&self, |
||||
signed_failure: SignedFailureNotification, |
||||
) -> Result<TxOutcome, ChainCommunicationError>; |
||||
} |
@ -0,0 +1,156 @@ |
||||
use async_trait::async_trait; |
||||
use ethers::contract::abigen; |
||||
use ethers::core::types::Address; |
||||
use optics_core::{ |
||||
traits::{ChainCommunicationError, ConnectionManager, TxOutcome}, |
||||
OpticsIdentifier, SignedFailureNotification, |
||||
}; |
||||
use std::sync::Arc; |
||||
|
||||
#[allow(missing_docs)] |
||||
abigen!( |
||||
EthereumConnectionManagerInternal, |
||||
"../abis/XAppConnectionManager.abi.json" |
||||
); |
||||
|
||||
/// A reference to a XAppConnectionManager contract on some Ethereum chain
|
||||
#[derive(Debug)] |
||||
pub struct EthereumConnectionManager<M> |
||||
where |
||||
M: ethers::providers::Middleware, |
||||
{ |
||||
contract: EthereumConnectionManagerInternal<M>, |
||||
domain: u32, |
||||
name: String, |
||||
} |
||||
|
||||
impl<M> EthereumConnectionManager<M> |
||||
where |
||||
M: ethers::providers::Middleware, |
||||
{ |
||||
/// Create a reference to a XAppConnectionManager at a specific Ethereum
|
||||
/// address on some chain
|
||||
#[allow(dead_code)] |
||||
pub fn new(name: &str, domain: u32, address: Address, provider: Arc<M>) -> Self { |
||||
Self { |
||||
contract: EthereumConnectionManagerInternal::new(address, provider), |
||||
domain, |
||||
name: name.to_owned(), |
||||
} |
||||
} |
||||
} |
||||
|
||||
#[async_trait] |
||||
impl<M> ConnectionManager for EthereumConnectionManager<M> |
||||
where |
||||
M: ethers::providers::Middleware + 'static, |
||||
{ |
||||
fn local_domain(&self) -> u32 { |
||||
self.domain |
||||
} |
||||
|
||||
#[tracing::instrument(err)] |
||||
async fn is_owner(&self, address: OpticsIdentifier) -> Result<bool, ChainCommunicationError> { |
||||
Ok(self |
||||
.contract |
||||
.is_owner(address.as_ethereum_address()) |
||||
.call() |
||||
.await?) |
||||
} |
||||
|
||||
#[tracing::instrument(err)] |
||||
async fn is_replica(&self, address: OpticsIdentifier) -> Result<bool, ChainCommunicationError> { |
||||
Ok(self |
||||
.contract |
||||
.is_replica(address.as_ethereum_address()) |
||||
.call() |
||||
.await?) |
||||
} |
||||
|
||||
#[tracing::instrument(err)] |
||||
async fn watcher_permission( |
||||
&self, |
||||
address: OpticsIdentifier, |
||||
domain: u32, |
||||
) -> Result<bool, ChainCommunicationError> { |
||||
Ok(self |
||||
.contract |
||||
.watcher_permission(address.as_ethereum_address(), domain) |
||||
.call() |
||||
.await?) |
||||
} |
||||
|
||||
#[tracing::instrument(err)] |
||||
async fn owner_enroll_replica( |
||||
&self, |
||||
replica: OpticsIdentifier, |
||||
domain: u32, |
||||
) -> Result<TxOutcome, ChainCommunicationError> { |
||||
Ok(self |
||||
.contract |
||||
.owner_enroll_replica(replica.as_ethereum_address(), domain) |
||||
.send() |
||||
.await? |
||||
.await? |
||||
.into()) |
||||
} |
||||
|
||||
#[tracing::instrument(err)] |
||||
async fn owner_unenroll_replica( |
||||
&self, |
||||
replica: OpticsIdentifier, |
||||
) -> Result<TxOutcome, ChainCommunicationError> { |
||||
Ok(self |
||||
.contract |
||||
.owner_unenroll_replica(replica.as_ethereum_address()) |
||||
.send() |
||||
.await? |
||||
.await? |
||||
.into()) |
||||
} |
||||
|
||||
#[tracing::instrument(err)] |
||||
async fn set_home(&self, home: OpticsIdentifier) -> Result<TxOutcome, ChainCommunicationError> { |
||||
Ok(self |
||||
.contract |
||||
.set_home(home.as_ethereum_address()) |
||||
.send() |
||||
.await? |
||||
.await? |
||||
.into()) |
||||
} |
||||
|
||||
#[tracing::instrument(err)] |
||||
async fn set_watcher_permission( |
||||
&self, |
||||
watcher: OpticsIdentifier, |
||||
domain: u32, |
||||
access: bool, |
||||
) -> Result<TxOutcome, ChainCommunicationError> { |
||||
Ok(self |
||||
.contract |
||||
.set_watcher_permission(watcher.as_ethereum_address(), domain, access) |
||||
.send() |
||||
.await? |
||||
.await? |
||||
.into()) |
||||
} |
||||
|
||||
#[tracing::instrument(err)] |
||||
async fn unenroll_replica( |
||||
&self, |
||||
signed_failure: SignedFailureNotification, |
||||
) -> Result<TxOutcome, ChainCommunicationError> { |
||||
Ok(self |
||||
.contract |
||||
.unenroll_replica( |
||||
signed_failure.notification.domain, |
||||
signed_failure.notification.updater.as_ethereum_address(), |
||||
signed_failure.signature.to_vec(), |
||||
) |
||||
.send() |
||||
.await? |
||||
.await? |
||||
.into()) |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,2 +1,3 @@ |
||||
cat artifacts/contracts/Replica.sol/Replica.json| jq .abi > ../../abis/Replica.abi.json && \ |
||||
cat artifacts/contracts/Home.sol/Home.json| jq .abi > ../../abis/Home.abi.json |
||||
cat artifacts/contracts/Home.sol/Home.json| jq .abi > ../../abis/Home.abi.json && \ |
||||
cat artifacts/contracts/XAppConnectionManager.sol/XAppConnectionManager.json | jq .abi > ../../abis/XAppConnectionManager.abi.json |
Loading…
Reference in new issue