You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
5.0 KiB
167 lines
5.0 KiB
4 years ago
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||
|
pragma solidity >=0.6.11;
|
||
|
|
||
4 years ago
|
import {BridgeMessage} from "./BridgeMessage.sol";
|
||
4 years ago
|
import {TokenRegistry} from "./TokenRegistry.sol";
|
||
4 years ago
|
import {BridgeToken} from "./BridgeToken.sol";
|
||
4 years ago
|
import {IBridgeToken} from "../../interfaces/token-bridge/IBridgeToken.sol";
|
||
4 years ago
|
|
||
4 years ago
|
import {Home} from "@celo-org/optics-sol/contracts/Home.sol";
|
||
4 years ago
|
import {
|
||
|
TypeCasts
|
||
|
} from "@celo-org/optics-sol/contracts/XAppConnectionManager.sol";
|
||
4 years ago
|
import {
|
||
4 years ago
|
IMessageRecipient
|
||
|
} from "@celo-org/optics-sol/interfaces/IMessageRecipient.sol";
|
||
4 years ago
|
|
||
|
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||
|
import {TypedMemView} from "@summa-tx/memview-sol/contracts/TypedMemView.sol";
|
||
|
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
|
||
|
|
||
4 years ago
|
contract BridgeRouter is IMessageRecipient, TokenRegistry {
|
||
4 years ago
|
using TypedMemView for bytes;
|
||
|
using TypedMemView for bytes29;
|
||
|
using BridgeMessage for bytes29;
|
||
|
using SafeERC20 for IERC20;
|
||
|
|
||
|
mapping(uint32 => bytes32) internal remotes;
|
||
|
|
||
4 years ago
|
constructor(address _xAppConnectionManager)
|
||
|
TokenRegistry(_xAppConnectionManager)
|
||
4 years ago
|
{} // solhint-disable-line no-empty-blocks
|
||
4 years ago
|
|
||
|
modifier onlyRemoteRouter(uint32 _origin, bytes32 _router) {
|
||
4 years ago
|
require(_isRemoteRouter(_origin, _router), "Not a remote router");
|
||
4 years ago
|
_;
|
||
|
}
|
||
|
|
||
4 years ago
|
function enrollRemote(uint32 _origin, bytes32 _router) external onlyOwner {
|
||
|
remotes[_origin] = _router;
|
||
|
}
|
||
|
|
||
4 years ago
|
function handle(
|
||
|
uint32 _origin,
|
||
|
bytes32 _sender,
|
||
|
bytes memory _message
|
||
|
)
|
||
|
external
|
||
|
override
|
||
|
onlyReplica
|
||
|
onlyRemoteRouter(_origin, _sender)
|
||
|
returns (bytes memory)
|
||
|
{
|
||
|
bytes29 _msg = _message.ref(0).mustBeMessage();
|
||
|
bytes29 _tokenId = _msg.tokenId();
|
||
|
bytes29 _action = _msg.action();
|
||
|
if (_action.isTransfer()) {
|
||
4 years ago
|
return _handleTransfer(_tokenId, _action);
|
||
4 years ago
|
}
|
||
|
if (_action.isDetails()) {
|
||
4 years ago
|
return _handleDetails(_tokenId, _action);
|
||
4 years ago
|
}
|
||
|
require(false, "!action");
|
||
|
return hex"";
|
||
|
}
|
||
|
|
||
|
function send(
|
||
|
address _token,
|
||
|
uint32 _destination,
|
||
|
bytes32 _recipient,
|
||
|
uint256 _amnt
|
||
|
) external {
|
||
4 years ago
|
bytes32 _remote = _mustHaveRemote(_destination);
|
||
|
IERC20 _bridgeToken = IERC20(_token);
|
||
4 years ago
|
|
||
4 years ago
|
if (_isNative(_bridgeToken)) {
|
||
|
_bridgeToken.safeTransferFrom(msg.sender, address(this), _amnt);
|
||
4 years ago
|
} else {
|
||
4 years ago
|
_downcast(_bridgeToken).burn(msg.sender, _amnt);
|
||
4 years ago
|
}
|
||
|
|
||
4 years ago
|
TokenId memory _tokId = _tokenIdFor(_token);
|
||
4 years ago
|
bytes29 _tokenId =
|
||
|
BridgeMessage.formatTokenId(_tokId.domain, _tokId.id);
|
||
|
bytes29 _action = BridgeMessage.formatTransfer(_recipient, _amnt);
|
||
|
|
||
4 years ago
|
Home(xAppConnectionManager.home()).enqueue(
|
||
4 years ago
|
_destination,
|
||
|
_remote,
|
||
|
BridgeMessage.formatMessage(_tokenId, _action)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
function updateDetails(address _token, uint32 _destination) external {
|
||
4 years ago
|
bytes32 _remote = _mustHaveRemote(_destination);
|
||
|
IBridgeToken _bridgeToken = IBridgeToken(_token);
|
||
4 years ago
|
|
||
4 years ago
|
TokenId memory _tokId = _tokenIdFor(_token);
|
||
4 years ago
|
bytes29 _tokenId =
|
||
|
BridgeMessage.formatTokenId(_tokId.domain, _tokId.id);
|
||
|
|
||
|
bytes29 _action =
|
||
|
BridgeMessage.formatDetails(
|
||
4 years ago
|
TypeCasts.coerceBytes32(_bridgeToken.name()),
|
||
|
TypeCasts.coerceBytes32(_bridgeToken.symbol()),
|
||
|
_bridgeToken.decimals()
|
||
4 years ago
|
);
|
||
|
|
||
4 years ago
|
Home(xAppConnectionManager.home()).enqueue(
|
||
4 years ago
|
_destination,
|
||
|
_remote,
|
||
|
BridgeMessage.formatMessage(_tokenId, _action)
|
||
|
);
|
||
|
}
|
||
4 years ago
|
|
||
4 years ago
|
function _handleTransfer(bytes29 _tokenId, bytes29 _action)
|
||
4 years ago
|
internal
|
||
|
typeAssert(_tokenId, BridgeMessage.Types.TokenId)
|
||
|
typeAssert(_action, BridgeMessage.Types.Transfer)
|
||
|
returns (bytes memory)
|
||
|
{
|
||
4 years ago
|
IERC20 _token = _ensureToken(_tokenId);
|
||
4 years ago
|
|
||
4 years ago
|
if (_isNative(_token)) {
|
||
4 years ago
|
_token.safeTransfer(_action.evmRecipient(), _action.amnt());
|
||
|
} else {
|
||
4 years ago
|
_downcast(_token).mint(_action.evmRecipient(), _action.amnt());
|
||
4 years ago
|
}
|
||
|
|
||
|
return hex"";
|
||
|
}
|
||
|
|
||
4 years ago
|
function _handleDetails(bytes29 _tokenId, bytes29 _action)
|
||
4 years ago
|
internal
|
||
|
typeAssert(_tokenId, BridgeMessage.Types.TokenId)
|
||
|
typeAssert(_action, BridgeMessage.Types.Details)
|
||
|
returns (bytes memory)
|
||
|
{
|
||
4 years ago
|
IERC20 _token = _ensureToken(_tokenId);
|
||
|
require(!_isNative(_token), "!repr");
|
||
4 years ago
|
|
||
4 years ago
|
_downcast(_token).setDetails(
|
||
4 years ago
|
_action.name(),
|
||
|
_action.symbol(),
|
||
|
_action.decimals()
|
||
|
);
|
||
|
|
||
|
return hex"";
|
||
|
}
|
||
|
|
||
4 years ago
|
function _mustHaveRemote(uint32 _domain)
|
||
4 years ago
|
internal
|
||
|
view
|
||
|
returns (bytes32 _remote)
|
||
|
{
|
||
|
_remote = remotes[_domain];
|
||
|
require(_remote != bytes32(0), "!remote");
|
||
|
}
|
||
|
|
||
4 years ago
|
function _isRemoteRouter(uint32 _origin, bytes32 _router)
|
||
4 years ago
|
internal
|
||
|
view
|
||
|
returns (bool)
|
||
|
{
|
||
|
return remotes[_origin] == _router;
|
||
|
}
|
||
4 years ago
|
}
|