feature: adds XAppConnectionManager interface (#273)

buddies-main-deployment
Luke Tchang 4 years ago committed by GitHub
parent d3788f0457
commit 03fa9bcded
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 338
      abis/XAppConnectionManager.abi.json
  2. 4
      rust/optics-core/src/lib.rs
  3. 4
      rust/optics-core/src/traits/mod.rs
  4. 56
      rust/optics-core/src/traits/xapp.rs
  5. 4
      rust/optics-ethereum/src/lib.rs
  6. 156
      rust/optics-ethereum/src/xapp.rs
  7. 5
      solidity/optics-bridge/contracts/BridgeRouter.sol
  8. 400
      solidity/optics-bridge/package-lock.json
  9. 12
      solidity/optics-core/contracts/XAppConnectionManager.sol
  10. 11
      solidity/optics-core/contracts/governance/GovernanceRouter.sol
  11. 400
      solidity/optics-core/package-lock.json
  12. 3
      solidity/optics-core/scripts/update_abis.sh

@ -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"
}
]

@ -32,6 +32,7 @@ mod utils;
use std::convert::Infallible;
pub use encode::{Decode, Encode};
pub use identifiers::OpticsIdentifier;
use async_trait::async_trait;
use ethers::{
@ -41,7 +42,6 @@ use ethers::{
},
signers::Signer,
};
use identifiers::OpticsIdentifier;
use ethers::signers::LocalWallet;
#[cfg(feature = "yubi")]
@ -386,6 +386,7 @@ impl SignedUpdate {
}
/// Failure notification produced by watcher
#[derive(Debug)]
pub struct FailureNotification {
/// Domain of replica to unenroll
pub domain: u32,
@ -423,6 +424,7 @@ impl FailureNotification {
}
/// Signed failure notification produced by watcher
#[derive(Debug)]
pub struct SignedFailureNotification {
/// Failure notification
pub notification: FailureNotification,

@ -4,6 +4,9 @@ pub mod home;
/// Interface for replica chain contract
pub mod replica;
/// Interface for XAppConnectionManager contract
pub mod xapp;
use async_trait::async_trait;
use ethers::{
contract::ContractError,
@ -16,6 +19,7 @@ use crate::{OpticsError, SignedUpdate};
pub use home::*;
pub use replica::*;
pub use xapp::*;
/// Contract states
#[derive(Debug)]

@ -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>;
}

@ -12,6 +12,10 @@ mod home;
#[cfg(not(doctest))]
mod replica;
/// XAppConnectionManager abi
#[cfg(not(doctest))]
mod xapp;
/// Base trait for an agent
mod utils;

@ -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())
}
}

@ -6,6 +6,7 @@ import {TokenRegistry} from "./TokenRegistry.sol";
import {BridgeToken} from "./BridgeToken.sol";
import {BridgeTokenI} from "../interfaces/BridgeTokenI.sol";
import {Home} from "@celo-org/optics-sol/contracts/Home.sol";
import {
TypeCasts
} from "@celo-org/optics-sol/contracts/XAppConnectionManager.sol";
@ -135,7 +136,7 @@ contract BridgeRouter is MessageRecipientI, TokenRegistry {
BridgeMessage.formatTokenId(_tokId.domain, _tokId.id);
bytes29 _action = BridgeMessage.formatTransfer(_recipient, _amnt);
xAppConnectionManager.enqueueHome(
Home(xAppConnectionManager.home()).enqueue(
_destination,
_remote,
BridgeMessage.formatMessage(_tokenId, _action)
@ -157,7 +158,7 @@ contract BridgeRouter is MessageRecipientI, TokenRegistry {
_tok.decimals()
);
xAppConnectionManager.enqueueHome(
Home(xAppConnectionManager.home()).enqueue(
_destination,
_remote,
BridgeMessage.formatMessage(_tokenId, _action)

File diff suppressed because it is too large Load Diff

@ -91,12 +91,12 @@ contract XAppConnectionManager is Ownable {
return home.originDomain();
}
function enqueueHome(
uint32 _destination,
bytes32 _recipient,
bytes memory _body
) public {
home.enqueue(_destination, _recipient, _body);
function watcherPermission(address _watcher, uint32 _domain)
public
view
returns (bool)
{
return watcherPermissions[_watcher][_domain];
}
function unenrollReplica(address _replica) internal {

@ -4,6 +4,7 @@ pragma experimental ABIEncoderV2;
import {TypedMemView} from "@summa-tx/memview-sol/contracts/TypedMemView.sol";
import {Home} from "../Home.sol";
import {XAppConnectionManager, TypeCasts} from "../XAppConnectionManager.sol";
import {MessageRecipientI} from "../../interfaces/MessageRecipientI.sol";
import {GovernanceMessage} from "./GovernanceMessage.sol";
@ -225,7 +226,7 @@ contract GovernanceRouter is MessageRecipientI {
bytes32 _router = mustHaveRouter(_destination);
bytes memory _msg = GovernanceMessage.formatCalls(calls);
xAppConnectionManager.enqueueHome(_destination, _router, _msg);
Home(xAppConnectionManager.home()).enqueue(_destination, _router, _msg);
}
function transferGovernor(uint32 _newDomain, address _newGovernor)
@ -264,13 +265,11 @@ contract GovernanceRouter is MessageRecipientI {
}
function _sendToAllRemoteRouters(bytes memory _msg) internal {
Home home = Home(xAppConnectionManager.home());
for (uint256 i = 0; i < domains.length; i++) {
if (domains[i] != uint32(0)) {
xAppConnectionManager.enqueueHome(
domains[i],
routers[domains[i]],
_msg
);
home.enqueue(domains[i], routers[domains[i]], _msg);
}
}
}

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…
Cancel
Save