Skip to content

Commit

Permalink
Set up Axelar router (#55)
Browse files Browse the repository at this point in the history
* Set up axelar router

* Clean up

* Add axelar script, clean up

* Fix name

* Remove auth from axelar router as it's fully immutable

* Fix script
  • Loading branch information
Jeroen Offerijns committed Mar 22, 2023
1 parent 51d0696 commit 5f353bb
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 2 deletions.
33 changes: 33 additions & 0 deletions script/Connector-Axelar.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.18;

import {ConnectorAxelarRouter} from "src/routers/axelar/Router.sol";
import {CentrifugeConnector} from "src/Connector.sol";
import {ConnectorEscrow} from "src/Escrow.sol";
import {RestrictedTokenFactory, MemberlistFactory} from "src/token/factory.sol";
import "forge-std/Script.sol";

// Script to deploy Connectors with an Axelar router.
contract ConnectorAxelarScript is Script {
// address(0)[0:20] + heccak("Centrifuge")[21:32]
bytes32 SALT = 0x000000000000000000000000000000000000000075eb27011b69f002dc094d05;

function setUp() public {}

function run() public {
vm.startBroadcast();

address escrow_ = address(new ConnectorEscrow{ salt: SALT }());
address tokenFactory_ = address(new RestrictedTokenFactory{ salt: SALT }());
address memberlistFactory_ = address(new MemberlistFactory{ salt: SALT }());
CentrifugeConnector connector =
new CentrifugeConnector{ salt: SALT }(escrow_, tokenFactory_, memberlistFactory_);

ConnectorAxelarRouter router = new ConnectorAxelarRouter{ salt: SALT }(
address(connector),
address(vm.envAddress("AXELAR_GATEWAY"))
);
connector.file("router", address(router));
vm.stopBroadcast();
}
}
101 changes: 101 additions & 0 deletions src/routers/axelar/Router.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.18;
pragma abicoder v2;

import {TypedMemView} from "memview-sol/TypedMemView.sol";
import {ConnectorMessages} from "../../Messages.sol";

interface ConnectorLike {
function addPool(uint64 poolId) external;
function addTranche(
uint64 poolId,
bytes16 trancheId,
string memory tokenName,
string memory tokenSymbol,
uint128 price
) external;
function updateMember(uint64 poolId, bytes16 trancheId, address user, uint64 validUntil) external;
function updateTokenPrice(uint64 poolId, bytes16 trancheId, uint128 price) external;
function handleTransfer(uint64 poolId, bytes16 trancheId, address destinationAddress, uint128 amount) external;
}

interface AxelarExecutableLike {
function execute(
bytes32 commandId,
string calldata sourceChain,
string calldata sourceAddress,
bytes calldata payload
) external;
}

interface AxelarGatewayLike {
function callContract(string calldata destinationChain, string calldata contractAddress, bytes calldata payload)
external;
}

contract ConnectorAxelarRouter is AxelarExecutableLike {
using TypedMemView for bytes;
// why bytes29? - https://github.com/summa-tx/memview-sol#why-bytes29
using TypedMemView for bytes29;
using ConnectorMessages for bytes29;

ConnectorLike public immutable connector;
AxelarGatewayLike public immutable axelarGateway;

string public constant axelarCentrifugeChainId = "Centrifuge";
string public constant axelarCentrifugeChainAddress = "";

constructor(address connector_, address axelarGateway_) {
connector = ConnectorLike(connector_);
axelarGateway = AxelarGatewayLike(axelarGateway_);
}

modifier onlyCentrifugeChainOrigin(string memory sourceChain) {
require(
msg.sender == address(axelarGateway)
&& keccak256(bytes(axelarCentrifugeChainId)) == keccak256(bytes(sourceChain)),
"ConnectorAxelarRouter/invalid-origin"
);
_;
}

modifier onlyConnector() {
require(msg.sender == address(connector), "ConnectorAxelarRouter/only-connector-allowed-to-call");
_;
}

// --- Incoming ---
function execute(bytes32, string calldata sourceChain, string calldata, bytes calldata payload)
external
onlyCentrifugeChainOrigin(sourceChain)
{
bytes29 _msg = payload.ref(0);

if (ConnectorMessages.isAddPool(_msg)) {
uint64 poolId = ConnectorMessages.parseAddPool(_msg);
connector.addPool(poolId);
} else if (ConnectorMessages.isAddTranche(_msg)) {
(uint64 poolId, bytes16 trancheId, string memory tokenName, string memory tokenSymbol, uint128 price) =
ConnectorMessages.parseAddTranche(_msg);
connector.addTranche(poolId, trancheId, tokenName, tokenSymbol, price);
} else if (ConnectorMessages.isUpdateMember(_msg)) {
(uint64 poolId, bytes16 trancheId, address user, uint64 validUntil) =
ConnectorMessages.parseUpdateMember(_msg);
connector.updateMember(poolId, trancheId, user, validUntil);
} else if (ConnectorMessages.isUpdateTokenPrice(_msg)) {
(uint64 poolId, bytes16 trancheId, uint128 price) = ConnectorMessages.parseUpdateTokenPrice(_msg);
connector.updateTokenPrice(poolId, trancheId, price);
} else if (ConnectorMessages.isTransfer(_msg)) {
(uint64 poolId, bytes16 trancheId,, address destinationAddress, uint128 amount) =
ConnectorMessages.parseTransfer20(_msg);
connector.handleTransfer(poolId, trancheId, destinationAddress, amount);
} else {
require(false, "invalid-message");
}
}

// --- Outgoing ---
function send(bytes memory message) public onlyConnector {
axelarGateway.callContract(axelarCentrifugeChainId, axelarCentrifugeChainAddress, message);
}
}
2 changes: 1 addition & 1 deletion src/routers/xcm/Router.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ contract ConnectorXCMRouter {
uint8 public immutable centrifugeChainConnectorsPalletIndex;
uint8 public immutable centrifugeChainConnectorsPalletHandleIndex;

/// --- Events ---
// --- Events ---
event Rely(address indexed user);
event Deny(address indexed user);
event File(bytes32 indexed what, XcmWeightInfo xcmWeightInfo);
Expand Down
2 changes: 1 addition & 1 deletion src/token/restricted.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ interface RestrictedTokenLike is ERC20Like {
contract RestrictedToken is ERC20 {
MemberlistLike public memberlist;

/// --- Events ---
// --- Events ---
event File(bytes32 indexed what, address data);

constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_, decimals_) {}
Expand Down

0 comments on commit 5f353bb

Please sign in to comment.