Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adapters - v0.2.0 #38

Merged
merged 36 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c3e0c5b
feat(evm): adds Reporter
allemanfredi Jan 24, 2024
2e1354c
feat(evm): adds tests for Reporter and aligns the Yaho and Yaru ones
allemanfredi Jan 24, 2024
3fa6771
refactor(evm): changes OracleAdapter comments
allemanfredi Jan 24, 2024
4dd3008
chore(evm): rm AMBHeaderReporter and AMBMessageRelayer
allemanfredi Jan 24, 2024
503e379
feat(evm): adds AMBReporter
allemanfredi Jan 24, 2024
33b730f
feat(evm): improve AMBAdapter
allemanfredi Jan 24, 2024
9b71c67
feat(evm): adds storeHashes within OracleAdapter
allemanfredi Jan 24, 2024
4c09010
refactor(evm): rn _sendPayload into _dispatch and adds missing PROVIDER
allemanfredi Jan 24, 2024
113c3da
refactor(evm): rm OracleAdapter from AMBAdapter
allemanfredi Jan 24, 2024
65a191a
refactor(evm): normalizes comments within BlockHashOracleAdapter
allemanfredi Jan 24, 2024
e61e8b0
refactor(evm): refactors Axelar adapter
allemanfredi Jan 24, 2024
59accd7
refactor(evm): rn Axelar adapter/reporter fxs
allemanfredi Jan 24, 2024
2129df0
refactor(evm): rn fx and event within AxelarAdapter
allemanfredi Jan 24, 2024
1021b5b
refactor(evm): refactors Celer Adapter and adds Reporter
allemanfredi Jan 24, 2024
ff28b1d
feat(evm): adds CCIPReporter and refactors CCIPAdapter
allemanfredi Jan 24, 2024
6dbcf7b
refactor(evm): rn vars
allemanfredi Jan 24, 2024
dd8d57a
feat(evm): adds ConnextReporter and refactors ConnextAdapter
allemanfredi Jan 24, 2024
f424603
refactor(evm): mv event position within ConnextReporter
allemanfredi Jan 24, 2024
0df3a60
refactor(evm): changes mapping key types within ConnextAdapter
allemanfredi Jan 24, 2024
8f11eff
feat(evm): adds HyperlaneReporter and refactors HyperlaneAdapter
allemanfredi Jan 24, 2024
43bef50
feat(evm): adds LayerZeroReporter and refactors LayerZeroAdapter
allemanfredi Jan 24, 2024
279d668
chore(evm): rm axiom adapter
allemanfredi Jan 24, 2024
74a903a
refactor(evm): adds _storeHashes within AMBAdapter
allemanfredi Jan 24, 2024
609e597
refactor(evm): refactors Optimism Adapter and adds the Reporter
allemanfredi Jan 24, 2024
e9bd59e
refactor(evm): makes hashes private within OracleAdapter
allemanfredi Jan 24, 2024
3d081a8
refactor(evm): rm OracleAdapter from L2CrossDomainMessengerAdapter
allemanfredi Jan 24, 2024
cfdd19b
refactor(evm): normalizes optismism Reporter and Adapter PROVIDER
allemanfredi Jan 24, 2024
5b113c0
refactor(evm): refactors Wormhole Adapter and adds the Reporter
allemanfredi Jan 24, 2024
05102e8
refactor(evm): refactors ZetaChain Adapter and adds the Reporter
allemanfredi Jan 24, 2024
26e40a6
refactor(evm): refactors PNetwork Adapter and adds the Reporter
allemanfredi Jan 25, 2024
4cdd184
refactor(evm): refactors Sygma Adapter and adds the Reporter
allemanfredi Jan 25, 2024
7db15f0
chore(test): rm AMB, PNetwork and Sygma tests
allemanfredi Jan 25, 2024
665cd46
chore(evm): rm HeaderOracleAdapter, HeaderReporter and MessageRelay
allemanfredi Jan 25, 2024
41dcf9f
Merge branch feat/v0.2.0 into feat/v0.2.0-adapters
allemanfredi Jan 25, 2024
8d50124
Merge branch 'feat/v0.2.0' into feat/v0.2.0-adapters
allemanfredi Jan 26, 2024
3c55b2f
chore(evm): rn Reporter test file
allemanfredi Jan 26, 2024
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
47 changes: 21 additions & 26 deletions packages/evm/contracts/adapters/AMB/AMBAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,37 @@
pragma solidity ^0.8.17;

import { IAMB } from "./IAMB.sol";
import { OracleAdapter } from "../OracleAdapter.sol";
import { BlockHashOracleAdapter } from "../BlockHashOracleAdapter.sol";

contract AMBAdapter is OracleAdapter, BlockHashOracleAdapter {
IAMB public amb;
address public reporter;
bytes32 public chainId;
contract AMBAdapter is BlockHashOracleAdapter {
string public constant PROVIDER = "amb";

error ArrayLengthMissmatch(address emitter);
error UnauthorizedAMB(address emitter, address sender);
error UnauthorizedChainId(address emitter, bytes32 chainId);
error UnauthorizedHashReporter(address emitter, address reporter);
IAMB public immutable AMB;
address public immutable REPORTER;
bytes32 public immutable SOURCE_CHAIN_ID;

constructor(IAMB _amb, address _reporter, bytes32 _chainId) {
amb = _amb;
reporter = _reporter;
chainId = _chainId;
error ArrayLengthMissmatch();
error UnauthorizedAMB(address sender, address expectedSender);
error UnauthorizedChainId(bytes32 sourceChainId, bytes32 expectedSourceChainId);
error UnauthorizedHashReporter(address reporter, address expectedReporter);

constructor(address amb, address reporter, bytes32 sourceChainId) {
AMB = IAMB(amb);
REPORTER = reporter;
SOURCE_CHAIN_ID = sourceChainId;
}

/// @dev Check that the amb, chainId, and owner are valid.
modifier onlyValid() {
if (msg.sender != address(amb)) revert UnauthorizedAMB(address(this), msg.sender);
if (amb.messageSourceChainId() != chainId) revert UnauthorizedChainId(address(this), chainId);
if (amb.messageSender() != reporter) revert UnauthorizedHashReporter(address(this), reporter);
bytes32 ambSourceChainId = AMB.messageSourceChainId();
address ambMessageSender = AMB.messageSender();
if (msg.sender != address(AMB)) revert UnauthorizedAMB(msg.sender, address(AMB));
if (ambSourceChainId != SOURCE_CHAIN_ID) revert UnauthorizedChainId(ambSourceChainId, SOURCE_CHAIN_ID);
if (ambMessageSender != REPORTER) revert UnauthorizedHashReporter(ambMessageSender, REPORTER);
_;
}

/// @dev Stores the hashes for a given array of idss.
/// @param ids Array of ids number for which to set the hashes.
/// @param _hashes Array of hashes to set for the given ids.
/// @notice Only callable by `amb` with a message passed from `reporter.
/// @notice Will revert if given array lengths do not match.
function storeHashes(uint256[] memory ids, bytes32[] memory _hashes) public onlyValid {
if (ids.length != _hashes.length) revert ArrayLengthMissmatch(address(this));
for (uint256 i = 0; i < ids.length; i++) {
_storeHash(uint256(chainId), ids[i], _hashes[i]);
}
if (ids.length != _hashes.length) revert ArrayLengthMissmatch();
_storeHashes(uint256(SOURCE_CHAIN_ID), ids, _hashes);
}
}
35 changes: 0 additions & 35 deletions packages/evm/contracts/adapters/AMB/AMBHeaderReporter.sol

This file was deleted.

30 changes: 0 additions & 30 deletions packages/evm/contracts/adapters/AMB/AMBMessageRelayer.sol

This file was deleted.

40 changes: 40 additions & 0 deletions packages/evm/contracts/adapters/AMB/AMBReporter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.17;

import { Reporter } from "../Reporter.sol";
import { AMBAdapter } from "./AMBAdapter.sol";
import { IOracleAdapter } from "../../interfaces/IOracleAdapter.sol";
import { IAMB } from "./IAMB.sol";

contract AMBReporter is Reporter {
string public constant PROVIDER = "amb";

address public immutable AMB;
uint256 public immutable GAS;
uint256 public immutable TO_CHAIN_ID;

error InvalidToChainId(uint256 chainId, uint256 expectedChainId);

constructor(
address headerStorage,
address yaho,
address amb,
uint256 toChainId,
uint256 gas
) Reporter(headerStorage, yaho) {
AMB = amb;
TO_CHAIN_ID = toChainId;
GAS = gas;
}

function _dispatch(
uint256 toChainId,
address adapter,
uint256[] memory ids,
bytes32[] memory hashes
) internal override returns (bytes32) {
if (toChainId != TO_CHAIN_ID) revert InvalidToChainId(toChainId, TO_CHAIN_ID);
bytes memory payload = abi.encodeCall(AMBAdapter.storeHashes, (ids, hashes));
return IAMB(AMB).requireToPassMessage(adapter, payload, GAS);
}
}
47 changes: 25 additions & 22 deletions packages/evm/contracts/adapters/Axelar/AxelarAdapter.sol
Original file line number Diff line number Diff line change
@@ -1,44 +1,47 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.17;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { AxelarExecutable } from "@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol";
import { HeaderOracleAdapter } from "../HeaderOracleAdapter.sol";
import { BlockHashOracleAdapter } from "../BlockHashOracleAdapter.sol";

contract AxelarAdapter is HeaderOracleAdapter, AxelarExecutable {
contract AxelarAdapter is BlockHashOracleAdapter, Ownable, AxelarExecutable {
string public constant PROVIDER = "axelar";
string public AXELAR_REPORTER_CHAIN; // Immutable
bytes32 public immutable AXELAR_REPORTER_CHAIN_HASH;
string public AXELAR_REPORTER_ADDRESS; // Immutable
bytes32 public immutable AXELAR_REPORTER_ADDRESS_HASH;

mapping(bytes32 => bytes32) public enabledReporters;
mapping(bytes32 => uint256) public chainIds;

error UnauthorizedAxelarReceive();
error ExecutionWithTokenNotSupported();

constructor(
uint256 reporterChain,
address reporterAddress,
address axelarGateway,
string memory axelarReporterChain,
string memory axelarReporterAddress
) HeaderOracleAdapter(reporterChain, reporterAddress) AxelarExecutable(axelarGateway) {
AXELAR_REPORTER_CHAIN = axelarReporterChain;
AXELAR_REPORTER_CHAIN_HASH = keccak256(bytes(axelarReporterChain));
AXELAR_REPORTER_ADDRESS = axelarReporterAddress;
AXELAR_REPORTER_ADDRESS_HASH = keccak256(bytes(axelarReporterAddress));
event ReporterSet(uint256 indexed chainId, string name, string indexed reporter);

constructor(address axelarGateway) AxelarExecutable(axelarGateway) {}

function setReporterByChain(
uint256 chainId,
string calldata chainName,
string calldata reporter
) external onlyOwner {
bytes32 chainNameHash = keccak256(bytes(chainName));
enabledReporters[chainNameHash] = keccak256(bytes(reporter));
chainIds[chainNameHash] = chainId;
emit ReporterSet(chainId, chainName, reporter);
}

function _execute(
string calldata sourceChain,
string calldata sourceAddress,
bytes calldata payload
) internal override {
if (
keccak256(bytes(sourceChain)) != AXELAR_REPORTER_CHAIN_HASH ||
keccak256(bytes(sourceAddress)) != AXELAR_REPORTER_ADDRESS_HASH
) {
bytes32 chainNameHash = keccak256(bytes(sourceChain));
bytes32 expectedSourceAddressHash = enabledReporters[chainNameHash];
uint256 sourceChainId = chainIds[chainNameHash];
if (expectedSourceAddressHash != keccak256(bytes(sourceAddress)) || sourceChainId == 0) {
revert UnauthorizedAxelarReceive();
}
_receivePayload(payload);
(uint256[] memory ids, bytes32[] memory hashes) = abi.decode(payload, (uint256[], bytes32[]));
_storeHashes(sourceChainId, ids, hashes);
}

function _executeWithToken(
Expand Down
19 changes: 0 additions & 19 deletions packages/evm/contracts/adapters/Axelar/AxelarHeaderReporter.sol

This file was deleted.

19 changes: 0 additions & 19 deletions packages/evm/contracts/adapters/Axelar/AxelarMessageRelay.sol

This file was deleted.

43 changes: 35 additions & 8 deletions packages/evm/contracts/adapters/Axelar/AxelarReporter.sol
Original file line number Diff line number Diff line change
@@ -1,37 +1,64 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.17;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { IAxelarGateway } from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol";
import { IAxelarGasService } from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol";
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { Reporter } from "../Reporter.sol";

abstract contract AxelarReporter {
contract AxelarReporter is Reporter, Ownable {
using Strings for uint256;

string public constant PROVIDER = "axelar";
bytes32 private constant NULL_STRING = keccak256("");
IAxelarGateway public immutable AXELAR_GATEWAY;
IAxelarGasService public immutable AXELAR_GAS_SERVICE;
string public AXELAR_ADAPTER_CHAIN; // Immutable

constructor(address axelarGateway, address axelarGasService, string memory axelarAdapterChain) {
mapping(uint256 => string) public chainNames;

error ChainIdNotSupported(uint256 chainId);

event ChainNameSet(uint256 indexed chainId, string indexed chainName);

constructor(
address headerStorage,
address yaho,
address axelarGateway,
address axelarGasService
) Reporter(headerStorage, yaho) {
AXELAR_GATEWAY = IAxelarGateway(axelarGateway);
AXELAR_GAS_SERVICE = IAxelarGasService(axelarGasService);
AXELAR_ADAPTER_CHAIN = axelarAdapterChain;
}

function _axelarSend(bytes memory payload, address adapter) internal {
function setChainNameByChainId(uint256 chainId, string calldata chainName) external onlyOwner {
chainNames[chainId] = chainName;
emit ChainNameSet(chainId, chainName);
}

function _dispatch(
uint256 toChainId,
address adapter,
uint256[] memory ids,
bytes32[] memory hashes
) internal override returns (bytes32) {
string memory chainName = chainNames[toChainId];
if (keccak256(abi.encode(chainName)) == NULL_STRING) revert ChainIdNotSupported(toChainId);

string memory sAdapter = uint256(uint160(adapter)).toHexString(20);
bytes memory payload = abi.encode(ids, hashes);

if (msg.value > 0) {
AXELAR_GAS_SERVICE.payNativeGasForContractCall{ value: msg.value }(
address(this),
AXELAR_ADAPTER_CHAIN,
chainName,
sAdapter,
payload,
msg.sender
);
}

AXELAR_GATEWAY.callContract(AXELAR_ADAPTER_CHAIN, sAdapter, payload);
AXELAR_GATEWAY.callContract(chainName, sAdapter, payload);
return bytes32(0);
}
}
11 changes: 4 additions & 7 deletions packages/evm/contracts/adapters/BlockHashOracleAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@
pragma solidity ^0.8.17;

import { RLPReader } from "solidity-rlp/contracts/RLPReader.sol";

import { OracleAdapter } from "./OracleAdapter.sol";
import { IBlockHashOracleAdapter } from "../interfaces/IBlockHashOracleAdapter.sol";

abstract contract BlockHashOracleAdapter is OracleAdapter {
abstract contract BlockHashOracleAdapter is IBlockHashOracleAdapter, OracleAdapter {
using RLPReader for RLPReader.RLPItem;

/// @dev Proves and stores valid ancestral block hashes for a given chain ID.
/// @param chainId The ID of the chain to prove block hashes for.
/// @param blockHeaders The RLP encoded block headers to prove the hashes for.
/// @notice Block headers should be ordered by descending block number and should start with a known block header.
/// @inheritdoc IBlockHashOracleAdapter
function proveAncestralBlockHashes(uint256 chainId, bytes[] memory blockHeaders) external {
for (uint256 i = 0; i < blockHeaders.length; i++) {
RLPReader.RLPItem memory blockHeaderRLP = RLPReader.toRlpItem(blockHeaders[i]);
Expand All @@ -28,7 +25,7 @@ abstract contract BlockHashOracleAdapter is OracleAdapter {
uint256 blockNumber = uint256(blockHeaderContent[8].toUint());

bytes32 reportedBlockHash = keccak256(blockHeaders[i]);
bytes32 storedBlockHash = hashes[chainId][blockNumber];
bytes32 storedBlockHash = getHashFromOracle(chainId, blockNumber);

if (reportedBlockHash != storedBlockHash)
revert ConflictingBlockHeader(blockNumber, reportedBlockHash, storedBlockHash);
Expand Down
Loading
Loading