Skip to content

Commit

Permalink
Merge branch 'main' into ci-implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
JordyRo1 committed May 6, 2024
2 parents 8c8de70 + 5cfb9b0 commit bf24594
Show file tree
Hide file tree
Showing 14 changed files with 1,487 additions and 91 deletions.
14 changes: 13 additions & 1 deletion Scarb.lock
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,20 @@ dependencies = [
]

[[package]]
name = "hyperlane_interfaces"
name = "hyperlane_starknet"
version = "0.1.0"
dependencies = [
"alexandria_bytes",
"openzeppelin",
"snforge_std",
]

[[package]]
name = "openzeppelin"
version = "0.10.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?rev=f22438c#f22438cca0e81c807d7c1742e83050ebd0ffcb3b"

[[package]]
name = "snforge_std"
version = "0.22.0"
source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.22.0#9b215944c6c5871c738381b4ded61bbf06e7ba35"
11 changes: 6 additions & 5 deletions Scarb.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
[workspace]
members = ["crates/hyperlane_interfaces"]
[package]
name = "hyperlane_starknet"
description = "Implementation of the Hyperlane protocol on Starknet."
version = "0.1.0"
Expand All @@ -8,14 +7,16 @@ cairo-version = "2.6.3"

# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html

[workspace.dependencies]
[dependencies]
starknet = "2.6.3"
alexandria_bytes = { git = "https://github.com/keep-starknet-strange/alexandria.git" }
openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", rev = "f22438c" }

[workspace.dev-dependencies]

[dev-dependencies]
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.22.0" }

[workspace.tool.fmt]
[tool.fmt]
sort-module-level-items = true

[[target.starknet-contract]]
Expand Down
13 changes: 0 additions & 13 deletions crates/hyperlane_interfaces/Scarb.toml

This file was deleted.

72 changes: 0 additions & 72 deletions crates/hyperlane_interfaces/src/lib.cairo

This file was deleted.

122 changes: 122 additions & 0 deletions src/contracts/client/mailboxclient.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#[starknet::contract]
mod mailboxclient {
use alexandria_bytes::{Bytes, BytesTrait, BytesStore};
use hyperlane_starknet::interfaces::{
IMailbox, IMailboxDispatcher, IMailboxDispatcherTrait, IInterchainSecurityModuleDispatcher,
IInterchainSecurityModuleDispatcherTrait, IMailboxClient,
};
use openzeppelin::access::ownable::OwnableComponent;
use openzeppelin::upgrades::{interface::IUpgradeable, upgradeable::UpgradeableComponent};
use starknet::{ContractAddress, contract_address_const, ClassHash};

component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);
#[abi(embed_v0)]
impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;
impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;
impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;


#[storage]
struct Storage {
mailbox: ContractAddress,
local_domain: u32,
hook: ContractAddress,
interchain_security_module: ContractAddress,
#[substorage(v0)]
ownable: OwnableComponent::Storage,
#[substorage(v0)]
upgradeable: UpgradeableComponent::Storage,
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
OwnableEvent: OwnableComponent::Event,
#[flat]
UpgradeableEvent: UpgradeableComponent::Event,
}


#[constructor]
fn constructor(ref self: ContractState, _mailbox: ContractAddress, _owner: ContractAddress) {
self.mailbox.write(_mailbox);
let mailbox = IMailboxDispatcher { contract_address: _mailbox };
let local_domain = mailbox.get_local_domain();
self.local_domain.write(local_domain);
self.ownable.initializer(_owner);
}
#[abi(embed_v0)]
impl Upgradeable of IUpgradeable<ContractState> {
fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {
self.ownable.assert_only_owner();
self.upgradeable._upgrade(new_class_hash);
}
}


#[abi(embed_v0)]
impl IMailboxClientImpl of IMailboxClient<ContractState> {
fn set_hook(ref self: ContractState, _hook: ContractAddress) {
self.ownable.assert_only_owner();
self.hook.write(_hook);
}

fn set_interchain_security_module(ref self: ContractState, _module: ContractAddress) {
self.ownable.assert_only_owner();
self.interchain_security_module.write(_module);
}

fn _MailboxClient_initialize(
ref self: ContractState,
_hook: ContractAddress,
_interchain_security_module: ContractAddress,
) {
self.ownable.assert_only_owner();
self.set_hook(_hook);
self.set_interchain_security_module(_interchain_security_module);
}

fn _is_latest_dispatched(self: @ContractState, _id: u256) -> bool {
let mailbox_address = self.mailbox.read();
let mailbox = IMailboxDispatcher { contract_address: mailbox_address };
mailbox.get_latest_dispatched_id() == _id
}

fn _is_delivered(self: @ContractState, _id: u256) -> bool {
let mailbox_address = self.mailbox.read();
let mailbox = IMailboxDispatcher { contract_address: mailbox_address };
mailbox.delivered(_id)
}

fn _dispatch(
self: @ContractState,
_destination_domain: u32,
_recipient: ContractAddress,
_message_body: Bytes,
_hook_metadata: Option<Bytes>,
_hook: Option<ContractAddress>
) -> u256 {
let mailbox_address = self.mailbox.read();
let mailbox = IMailboxDispatcher { contract_address: mailbox_address };
mailbox.dispatch(_destination_domain, _recipient, _message_body, _hook_metadata, _hook)
}

fn quote_dispatch(
self: @ContractState,
_destination_domain: u32,
_recipient: ContractAddress,
_message_body: Bytes,
_hook_metadata: Option<Bytes>,
_hook: Option<ContractAddress>
) -> u256 {
let mailbox_address = self.mailbox.read();
let mailbox = IMailboxDispatcher { contract_address: mailbox_address };
mailbox
.quote_dispatch(
_destination_domain, _recipient, _message_body, _hook_metadata, _hook
)
}
}
}
131 changes: 131 additions & 0 deletions src/contracts/client/router.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#[starknet::contract]
mod router {
use hyperlane_starknet::contracts::libs::message::Message;
use hyperlane_starknet::interfaces::IRouter;
use openzeppelin::access::ownable::OwnableComponent;
use openzeppelin::upgrades::{interface::IUpgradeable, upgradeable::UpgradeableComponent};

use starknet::{ContractAddress, get_caller_address, ClassHash, contract_address_const};
component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);
#[abi(embed_v0)]
impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;
impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;
impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;

type Domain = u32;
#[storage]
struct Storage {
routers: LegacyMap<Domain, ContractAddress>,
mailbox: ContractAddress,
#[substorage(v0)]
ownable: OwnableComponent::Storage,
#[substorage(v0)]
upgradeable: UpgradeableComponent::Storage,
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
OwnableEvent: OwnableComponent::Event,
#[flat]
UpgradeableEvent: UpgradeableComponent::Event,
}


mod Errors {
pub const LENGTH_MISMATCH: felt252 = 'Domains and Router len mismatch';
pub const CALLER_IS_NOT_MAILBOX: felt252 = 'Caller is not mailbox';
pub const NO_ROUTER_FOR_DOMAIN: felt252 = 'No router for domain';
pub const ENROLLED_ROUTER_AND_SENDER_MISMATCH: felt252 = 'Enrolled router/sender mismatch';
}

#[constructor]
fn constructor(ref self: ContractState, _mailbox: ContractAddress) {
self.mailbox.write(_mailbox);
}

#[abi(embed_v0)]
impl Upgradeable of IUpgradeable<ContractState> {
fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {
self.ownable.assert_only_owner();
self.upgradeable._upgrade(new_class_hash);
}
}

#[abi(embed_v0)]
impl IRouterImpl of IRouter<ContractState> {
fn routers(self: @ContractState, _domain: u32) -> ContractAddress {
self.routers.read(_domain)
}

fn unenroll_remote_router(ref self: ContractState, _domain: u32) {
self.ownable.assert_only_owner();
_unenroll_remote_router(ref self, _domain);
}

fn enroll_remote_router(ref self: ContractState, _domain: u32, _router: ContractAddress) {
self.ownable.assert_only_owner();
_enroll_remote_router(ref self, _domain, _router);
}

fn enroll_remote_routers(
ref self: ContractState, _domains: Span<u32>, _routers: Span<ContractAddress>
) {
self.ownable.assert_only_owner();
assert(_domains.len() == _routers.len(), Errors::LENGTH_MISMATCH);
let length = _domains.len();
let mut cur_idx = 0;
loop {
if (cur_idx == length) {
break ();
}
_enroll_remote_router(ref self, *_domains.at(cur_idx), *_routers.at(cur_idx));
cur_idx += 1;
}
}

fn unenroll_remote_routers(ref self: ContractState, _domains: Span<u32>) {
self.ownable.assert_only_owner();
let length = _domains.len();
let mut cur_idx = 0;
loop {
if (cur_idx == length) {
break ();
}
_unenroll_remote_router(ref self, *_domains.at(cur_idx));
cur_idx += 1;
}
}

fn handle(self: @ContractState, _origin: u32, _sender: ContractAddress, _message: Message) {
let caller = get_caller_address();
assert(caller == self.mailbox.read(), Errors::CALLER_IS_NOT_MAILBOX);
let router = _must_have_remote_router(self, _origin);
assert(router == _sender, Errors::ENROLLED_ROUTER_AND_SENDER_MISMATCH);
_handle(_origin, _sender, _message);
}
}

fn _unenroll_remote_router(ref self: ContractState, _domain: u32) {
self.routers.write(_domain, contract_address_const::<0>());
}

fn _enroll_remote_router(ref self: ContractState, _domain: u32, _address: ContractAddress) {
self.routers.write(_domain, _address);
}

fn _must_have_remote_router(self: @ContractState, _domain: u32) -> ContractAddress {
let router = self.routers.read(_domain);
assert(router != 0.try_into().unwrap(), Errors::NO_ROUTER_FOR_DOMAIN);
router
}

fn _is_remote_Router(self: @ContractState, _domain: u32, _address: ContractAddress) -> bool {
let router = self.routers.read(_domain);
router == _address
}

fn _handle(_origin: u32, _sender: ContractAddress, _message: Message) {}
}
Loading

0 comments on commit bf24594

Please sign in to comment.