Skip to content

Commit

Permalink
repair unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoch05 committed Sep 6, 2023
1 parent b804f3a commit d08fcc0
Show file tree
Hide file tree
Showing 18 changed files with 608 additions and 247 deletions.
27 changes: 18 additions & 9 deletions helix-contract/contracts/ln/LnDefaultBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ import "./base/LnDefaultBridgeTarget.sol";
import "./interface/ILowLevelMessager.sol";

contract LnDefaultBridge is Initializable, LnAccessController, LnDefaultBridgeSource, LnDefaultBridgeTarget {
struct MessagerService {
address sendService;
address receiveService;
}

// remoteChainId => messager
mapping(uint256=>address) public messagers;
mapping(uint256=>MessagerService) public messagers;

receive() external payable {}

Expand All @@ -20,9 +24,14 @@ contract LnDefaultBridge is Initializable, LnAccessController, LnDefaultBridgeSo
}

// the remote endpoint is unique, if we want multi-path to remote endpoint, then the messager should support multi-path
function setBridgeInfo(uint256 _remoteChainId, address _remoteBridge, address _messager) external onlyDao {
messagers[_remoteChainId] = _messager;
ILowLevelMessager(_messager).registerBridgePair(_remoteChainId, _remoteBridge);
function setSendService(uint256 _remoteChainId, address _remoteBridge, address _service) external onlyDao {
messagers[_remoteChainId].sendService = _service;
ILowLevelMessageSender(_service).registerRemoteReceiver(_remoteChainId, _remoteBridge);
}

function setReceiveService(uint256 _remoteChainId, address _remoteBridge, address _service) external onlyDao {
messagers[_remoteChainId].receiveService = _service;
ILowLevelMessageReceiver(_service).registerRemoteSender(_remoteChainId, _remoteBridge);
}

function updateFeeReceiver(address _receiver) external onlyDao {
Expand Down Expand Up @@ -50,14 +59,14 @@ contract LnDefaultBridge is Initializable, LnAccessController, LnDefaultBridgeSo
}

function _sendMessageToTarget(uint256 _remoteChainId, bytes memory _payload, bytes memory _extParams) internal override {
address messager = messagers[_remoteChainId];
require(messager != address(0), "invalid messager");
ILowLevelMessager(messager).sendMessage(_remoteChainId, _payload, _extParams);
address sendService = messagers[_remoteChainId].sendService;
require(sendService != address(0), "invalid messager");
ILowLevelMessageSender(sendService).sendMessage(_remoteChainId, _payload, _extParams);
}

function _verifyRemote(uint256 _remoteChainId) whenNotPaused internal view override {
address messager = messagers[_remoteChainId];
require(messager == msg.sender, "invalid messager");
address receiveService = messagers[_remoteChainId].receiveService;
require(receiveService == msg.sender, "invalid messager");
}
}

26 changes: 20 additions & 6 deletions helix-contract/contracts/ln/LnOppositeBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import "./base/LnOppositeBridgeTarget.sol";
import "./interface/ILowLevelMessager.sol";

contract LnOppositeBridge is Initializable, LnAccessController, LnOppositeBridgeSource, LnOppositeBridgeTarget {
mapping(uint256=>address) messagers;
struct MessagerService {
address sendService;
address receiveService;
}
mapping(uint256=>MessagerService) messagers;

receive() external payable {}

Expand All @@ -17,6 +21,16 @@ contract LnOppositeBridge is Initializable, LnAccessController, LnOppositeBridge
_updateFeeReceiver(_dao);
}

function setSendService(uint256 _remoteChainId, address _remoteBridge, address _service) external onlyDao {
messagers[_remoteChainId].sendService = _service;
ILowLevelMessageSender(_service).registerRemoteReceiver(_remoteChainId, _remoteBridge);
}

function setReceiveService(uint256 _remoteChainId, address _remoteBridge, address _service) external onlyDao {
messagers[_remoteChainId].receiveService = _service;
ILowLevelMessageReceiver(_service).registerRemoteSender(_remoteChainId, _remoteBridge);
}

function updateFeeReceiver(address _receiver) external onlyDao {
_updateFeeReceiver(_receiver);
}
Expand All @@ -42,14 +56,14 @@ contract LnOppositeBridge is Initializable, LnAccessController, LnOppositeBridge
}

function _sendMessageToTarget(uint256 _remoteChainId, bytes memory _payload, bytes memory _extParams) internal override {
address messager = messagers[_remoteChainId];
require(messager != address(0), "invalid messager");
ILowLevelMessager(messager).sendMessage(_remoteChainId, _payload, _extParams);
address sendService = messagers[_remoteChainId].sendService;
require(sendService != address(0), "invalid messager");
ILowLevelMessageSender(sendService).sendMessage(_remoteChainId, _payload, _extParams);
}

function _verifyRemote(uint256 _remoteChainId) whenNotPaused internal view override {
address messager = messagers[_remoteChainId];
require(messager == msg.sender, "invalid messager");
address receiveService = messagers[_remoteChainId].receiveService;
require(receiveService == msg.sender, "invalid messager");
}
}

1 change: 0 additions & 1 deletion helix-contract/contracts/ln/base/LnBridgeHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ library LnBridgeHelper {
uint256 constant public LIQUIDITY_FEE_RATE_BASE = 100000;

struct TransferParameter {
uint256 remoteChainId;
bytes32 previousTransferId;
address provider;
address sourceToken;
Expand Down
16 changes: 11 additions & 5 deletions helix-contract/contracts/ln/base/LnDefaultBridgeSource.sol
Original file line number Diff line number Diff line change
Expand Up @@ -240,16 +240,17 @@ contract LnDefaultBridgeSource {

function _slashAndRemoteReleaseCall(
LnBridgeHelper.TransferParameter memory _params,
uint256 _remoteChainId,
bytes32 _expectedTransferId
) internal view returns(bytes memory message) {
bytes32 key = keccak256(abi.encodePacked(_params.remoteChainId, _params.sourceToken, _params.targetToken));
bytes32 key = keccak256(abi.encodePacked(_remoteChainId, _params.sourceToken, _params.targetToken));
LnBridgeHelper.TokenInfo memory tokenInfo = tokenInfos[key];
require(tokenInfo.isRegistered, "token not registered");
uint112 targetAmount = LnBridgeHelper.sourceAmountToTargetAmount(tokenInfo, _params.amount);

bytes32 transferId = keccak256(abi.encodePacked(
block.chainid,
_params.remoteChainId,
_remoteChainId,
_params.previousTransferId,
_params.provider,
_params.sourceToken,
Expand All @@ -259,14 +260,15 @@ contract LnDefaultBridgeSource {
));
require(_expectedTransferId == transferId, "expected transfer id not match");
LockInfo memory lockInfo = lockInfos[transferId];
require(lockInfo.timestamp == _params.timestamp, "lock info not match");
require(lockInfo.timestamp == _params.timestamp, "invalid timestamp");
require(block.timestamp > lockInfo.timestamp + LnBridgeHelper.SLASH_EXPIRE_TIME, "invalid timestamp");
uint112 targetFee = LnBridgeHelper.sourceAmountToTargetAmount(tokenInfo, lockInfo.fee);
uint112 targetPenalty = LnBridgeHelper.sourceAmountToTargetAmount(tokenInfo, lockInfo.penalty);

message = abi.encodeWithSelector(
ILnDefaultBridgeTarget.slash.selector,
_params,
_remoteChainId,
msg.sender, // slasher
targetFee,
targetPenalty
Expand Down Expand Up @@ -301,13 +303,15 @@ contract LnDefaultBridgeSource {

function encodeSlashCall(
LnBridgeHelper.TransferParameter memory _params,
uint256 _remoteChainId,
address _slasher,
uint112 _fee,
uint112 _penalty
) public pure returns(bytes memory message) {
return abi.encodeWithSelector(
ILnDefaultBridgeTarget.slash.selector,
_params,
_remoteChainId,
_slasher,
_fee,
_penalty
Expand Down Expand Up @@ -338,15 +342,17 @@ contract LnDefaultBridgeSource {

function requestSlashAndRemoteRelease(
LnBridgeHelper.TransferParameter calldata _params,
uint256 _remoteChainId,
bytes32 _expectedTransferId,
bytes memory _extParams
) payable external {
bytes memory slashCallMessage = _slashAndRemoteReleaseCall(
_params,
_remoteChainId,
_expectedTransferId
);
_sendMessageToTarget(_params.remoteChainId, slashCallMessage, _extParams);
emit SlashRequest(_params.remoteChainId, _params.sourceToken, _params.targetToken, _expectedTransferId);
_sendMessageToTarget(_remoteChainId, slashCallMessage, _extParams);
emit SlashRequest(_remoteChainId, _params.sourceToken, _params.targetToken, _expectedTransferId);
}

function requestWithdrawMargin(
Expand Down
14 changes: 9 additions & 5 deletions helix-contract/contracts/ln/base/LnDefaultBridgeTarget.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,14 @@ contract LnDefaultBridgeTarget {

function transferAndReleaseMargin(
LnBridgeHelper.TransferParameter calldata _params,
uint256 _remoteChainId,
bytes32 _expectedTransferId
) external payable {
require(_params.provider == msg.sender, "invalid provider");
require(_params.previousTransferId == bytes32(0) || fillTransfers[_params.previousTransferId].timestamp > 0, "last transfer not filled");
bytes32 transferId = keccak256(abi.encodePacked(
_remoteChainId,
block.chainid,
_params.previousTransferId,
_params.provider,
_params.sourceToken,
Expand All @@ -79,7 +82,7 @@ contract LnDefaultBridgeTarget {

fillTransfers[transferId].timestamp = uint64(block.timestamp);
if (block.timestamp - LnBridgeHelper.SLASH_EXPIRE_TIME > _params.timestamp) {
bytes32 providerKey = LnBridgeHelper.getProviderKey(_params.remoteChainId, msg.sender, _params.sourceToken, _params.targetToken);
bytes32 providerKey = LnBridgeHelper.getProviderKey(_remoteChainId, msg.sender, _params.sourceToken, _params.targetToken);
tgtProviders[providerKey].lastExpireFillTime = uint64(block.timestamp);
}

Expand Down Expand Up @@ -165,15 +168,16 @@ contract LnDefaultBridgeTarget {

function slash(
LnBridgeHelper.TransferParameter memory _params,
uint256 _sourceChainId,
uint256 _remoteChainId,
address _slasher,
uint112 _fee,
uint112 _penalty
) external allowRemoteCall(_sourceChainId) {
) external allowRemoteCall(_remoteChainId) {
require(_params.previousTransferId == bytes32(0) || fillTransfers[_params.previousTransferId].timestamp > 0, "last transfer not filled");

bytes32 transferId = keccak256(abi.encodePacked(
_params.remoteChainId,
_remoteChainId,
block.chainid,
_params.previousTransferId,
_params.provider,
_params.sourceToken,
Expand All @@ -183,7 +187,7 @@ contract LnDefaultBridgeTarget {
));
FillTransfer memory fillTransfer = fillTransfers[transferId];
require(fillTransfer.slasher == address(0), "transfer has been slashed");
bytes32 providerKey = LnBridgeHelper.getProviderKey(_params.remoteChainId, _params.provider, _params.sourceToken, _params.targetToken);
bytes32 providerKey = LnBridgeHelper.getProviderKey(_remoteChainId, _params.provider, _params.sourceToken, _params.targetToken);
TargetProviderInfo memory providerInfo = tgtProviders[providerKey];
uint256 updatedMargin = providerInfo.margin;
// transfer is not filled
Expand Down
17 changes: 12 additions & 5 deletions helix-contract/contracts/ln/base/LnOppositeBridgeTarget.sol
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,12 @@ contract LnOppositeBridgeTarget {
// III. Both I and II => latestSlashTransferId is trusted if previousTransfer is normal relayed tranfer
function _fillTransfer(
LnBridgeHelper.TransferParameter calldata _params,
uint256 _remoteChainId,
bytes32 _expectedTransferId
) internal {
bytes32 transferId = keccak256(abi.encodePacked(
_remoteChainId,
block.chainid,
_params.previousTransferId,
_params.provider,
_params.sourceToken,
Expand All @@ -90,11 +93,12 @@ contract LnOppositeBridgeTarget {

function transferAndReleaseMargin(
LnBridgeHelper.TransferParameter calldata _params,
uint256 _remoteChainId,
bytes32 _expectedTransferId
) payable external {
// normal relay message, fill slasher as zero
require(_params.provider == msg.sender, "invalid provider");
_fillTransfer(_params, _expectedTransferId);
_fillTransfer(_params, _remoteChainId, _expectedTransferId);

emit TransferFilled(_expectedTransferId, address(0));
}
Expand All @@ -105,10 +109,11 @@ contract LnOppositeBridgeTarget {
// So we needs to carry the the previous shash transferId to ensure that the slash is continuous.
function _slashAndRemoteReleaseCall(
LnBridgeHelper.TransferParameter calldata _params,
uint256 _remoteChainId,
bytes32 _expectedTransferId
) internal returns(bytes memory message) {
require(block.timestamp > _params.timestamp + LnBridgeHelper.SLASH_EXPIRE_TIME, "slash time not expired");
_fillTransfer(_params, _expectedTransferId);
_fillTransfer(_params, _remoteChainId, _expectedTransferId);

// slasher = msg.sender
slashInfos[_expectedTransferId] = SlashInfo(_params.provider, _params.sourceToken, _params.targetToken, msg.sender, _params.timestamp);
Expand Down Expand Up @@ -149,9 +154,9 @@ contract LnOppositeBridgeTarget {
bytes32 _latestSlashTransferId,
bytes32 _transferId,
uint256 _timestamp,
address _provider,
address _sourceToken,
address _targetToken,
address _provider,
address _slasher
) internal view returns(bytes memory) {
return abi.encodeWithSelector(
Expand All @@ -171,15 +176,17 @@ contract LnOppositeBridgeTarget {

function requestSlashAndRemoteRelease(
LnBridgeHelper.TransferParameter calldata _params,
uint256 _remoteChainId,
bytes32 _expectedTransferId,
bytes memory _extParams
) payable external {
bytes memory slashCallMessage = _slashAndRemoteReleaseCall(
_params,
_remoteChainId,
_expectedTransferId
);
_sendMessageToTarget(_params.remoteChainId, slashCallMessage, _extParams);
emit SlashRequest(_params.remoteChainId, _params.sourceToken, _params.targetToken, _expectedTransferId);
_sendMessageToTarget(_remoteChainId, slashCallMessage, _extParams);
emit SlashRequest(_remoteChainId, _params.sourceToken, _params.targetToken, _expectedTransferId);
}

function requestRetrySlashAndRemoteRelease(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "../base/LnBridgeHelper.sol";
interface ILnDefaultBridgeTarget {
function slash(
LnBridgeHelper.TransferParameter memory params,
uint256 remoteChainId,
address slasher,
uint112 fee,
uint112 penalty
Expand Down
9 changes: 7 additions & 2 deletions helix-contract/contracts/ln/interface/ILowLevelMessager.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

interface ILowLevelMessager {
function registerBridgePair(uint256 remoteChainId, address remoteBridge) external;
interface ILowLevelMessageSender {
function registerRemoteReceiver(uint256 remoteChainId, address remoteBridge) external;
function sendMessage(uint256 remoteChainId, bytes memory message, bytes memory params) external payable;
}

interface ILowLevelMessageReceiver {
function registerRemoteSender(uint256 remoteChainId, address remoteBridge) external;
function recvMessage(address remoteSender, address localReceiver, bytes memory payload) external;
}
41 changes: 41 additions & 0 deletions helix-contract/contracts/ln/messager/Eth2ArbReceiveService.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

import "@arbitrum/nitro-contracts/src/libraries/AddressAliasHelper.sol";
import "../interface/ILowLevelMessager.sol";

// from ethereum to arbitrum messager
contract Eth2ArbReceiveService is ILowLevelMessageReceiver {
uint256 immutable public REMOTE_CHAINID;
address public remoteMessagerAlias;

mapping(address=>address) public appPairs;

modifier onlyRemoteBridge() {
require(msg.sender == remoteMessagerAlias, "invalid remote caller");
_;
}

constructor(uint256 _remoteChainId) {
REMOTE_CHAINID = _remoteChainId;
}

// only can be set once
function setRemoteMessager(address _remoteMessager) external {
require(remoteMessagerAlias == address(0), "remote exist");
remoteMessagerAlias = AddressAliasHelper.applyL1ToL2Alias(_remoteMessager);
}

function registerRemoteSender(uint256 _remoteChainId, address _remoteBridge) external {
require(_remoteChainId == REMOTE_CHAINID, "invalid remote chainId");
appPairs[msg.sender] = _remoteBridge;
}

function recvMessage(address _remoteApp, address _localApp, bytes memory _message) onlyRemoteBridge external {
address remoteAppAddress = appPairs[_localApp];
require(remoteAppAddress == _remoteApp, "invalid remote app");
(bool result,) = _localApp.call(_message);
require(result == true, "local call failed");
}
}

Loading

0 comments on commit d08fcc0

Please sign in to comment.