Skip to content

Commit

Permalink
[Feature] Implement support to teleport to DOT address (#158)
Browse files Browse the repository at this point in the history
  • Loading branch information
developeruche authored Apr 8, 2024
1 parent 592ca1a commit 144c652
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 33 deletions.
44 changes: 29 additions & 15 deletions evm/src/modules/TokenGateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct TeleportParams {
// Redeem Erc20 on the destination?
bool redeem;
// recipient address
address to;
bytes32 to;
// The Erc20 token to be used to swap for a fee
address feeToken;
// recipient state machine
Expand All @@ -45,9 +45,9 @@ struct Body {
// flag to redeem the erc20 asset on the destination
bool redeem;
// sender address
address from;
bytes32 from;
// recipient address
address to;
bytes32 to;
}

struct BodyWithCall {
Expand All @@ -58,9 +58,9 @@ struct BodyWithCall {
// flag to redeem the erc20 asset on the destination
bool redeem;
// sender address
address from;
bytes32 from;
// recipient address
address to;
bytes32 to;
// calldata to be sent to the destination contract along aside with the asset
bytes data;
}
Expand Down Expand Up @@ -141,7 +141,7 @@ contract TokenGateway is BaseIsmpModule {

// User has received some assets, source chain & nonce
event AssetReceived(bytes source, uint256 nonce);
event Teleport(address from, address to, uint256 amount, bool redeem, bytes32 requestCommitment);
event Teleport(bytes32 from, bytes32 to, uint256 amount, bool redeem, bytes32 requestCommitment);

// restricts call to `IIsmpHost`
modifier onlyIsmpHost() {
Expand Down Expand Up @@ -179,19 +179,20 @@ contract TokenGateway is BaseIsmpModule {
}

function teleport(TeleportParams memory params) public {
require(params.to != address(0), "Burn your funds some other way");
require(params.to != bytes32(0), "Burn your funds some other way");
require(params.amount > 100_000, "Amount too low");
require(params.feeToken != address(0), "Fee token not selected");

address from = msg.sender;
bytes32 fromBytes32 = addressToBytes32(msg.sender);
address erc20 = _erc20s[params.assetId];
address erc6160 = _erc6160s[params.assetId];
address feeToken = IIsmpHost(_host).feeToken();

bytes memory data = params.data.length > 0
? abi.encode(
BodyWithCall({
from: from,
from: fromBytes32,
to: params.to,
amount: params.amount,
assetId: params.assetId,
Expand All @@ -200,7 +201,7 @@ contract TokenGateway is BaseIsmpModule {
})
)
: abi.encode(
Body({from: from, to: params.to, amount: params.amount, assetId: params.assetId, redeem: params.redeem})
Body({from: fromBytes32, to: params.to, amount: params.amount, assetId: params.assetId, redeem: params.redeem})
);

if (erc20 != address(0) && !params.redeem) {
Expand Down Expand Up @@ -231,7 +232,7 @@ contract TokenGateway is BaseIsmpModule {
bytes32 commitment = IDispatcher(_host).dispatch(request);

emit Teleport({
from: from,
from: fromBytes32,
to: params.to,
amount: params.amount,
redeem: params.redeem,
Expand Down Expand Up @@ -261,11 +262,12 @@ contract TokenGateway is BaseIsmpModule {

address erc20 = _erc20s[body.assetId];
address erc6160 = _erc6160s[body.assetId];
address fromAddress = bytes32ToAddress(body.from);

if (erc20 != address(0) && !body.redeem) {
require(IERC20(erc20).transfer(body.from, body.amount), "Gateway: Insufficient Balance");
require(IERC20(erc20).transfer(fromAddress, body.amount), "Gateway: Insufficient Balance");
} else if (erc6160 != address(0)) {
IERC6160Ext20(erc6160).mint(body.from, body.amount, "");
IERC6160Ext20(erc6160).mint(fromAddress, body.amount, "");
} else {
revert("Gateway: Inconsistent State");
}
Expand All @@ -276,7 +278,9 @@ contract TokenGateway is BaseIsmpModule {
require(request.from.equals(abi.encodePacked(address(this))), "Unauthorized request");
Body memory body = abi.decode(request.body[1:], (Body));

_handleIncomingAsset(body.assetId, body.redeem, body.amount, body.to);
address toAddress = bytes32ToAddress(body.to);

_handleIncomingAsset(body.assetId, body.redeem, body.amount, toAddress);

emit AssetReceived(request.source, request.nonce);
}
Expand All @@ -286,10 +290,12 @@ contract TokenGateway is BaseIsmpModule {
require(request.from.equals(abi.encodePacked(address(this))), "Unauthorized request");
BodyWithCall memory body = abi.decode(request.body[1:], (BodyWithCall));

_handleIncomingAsset(body.assetId, body.redeem, body.amount, body.to);
address toAddress = bytes32ToAddress(body.to);

_handleIncomingAsset(body.assetId, body.redeem, body.amount, toAddress);

// dispatching low level call
_dispatcher.dispatch(body.to, body.data);
_dispatcher.dispatch(toAddress, body.data);

emit AssetReceived(request.source, request.nonce);
}
Expand Down Expand Up @@ -387,4 +393,12 @@ contract TokenGateway is BaseIsmpModule {
_erc6160s[asset.identifier] = asset.erc6160;
}
}

function addressToBytes32(address _address) internal pure returns (bytes32) {
return bytes32(uint256(uint160(_address)));
}

function bytes32ToAddress(bytes32 _bytes) internal pure returns (address) {
return address(uint160(uint256(_bytes)));
}
}
11 changes: 10 additions & 1 deletion evm/test/TeleportSwapTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ contract TeleportSwapTest is MainnetForkBaseTest {
dest: StateMachine.bsc(),
fee: 9 * 1e17, // $0.9
timeout: 0,
to: address(this),
to: addressToBytes32(address(this)),
assetId: keccak256("USD.h"),
data: new bytes(0),
amountInMax: _amountInMax
Expand All @@ -55,4 +55,13 @@ contract TeleportSwapTest is MainnetForkBaseTest {
assert(feeToken.balanceOf(address(this)) == 0);
assert(feeToken.balanceOf(address(host)) == messagingFee);
}
}


function addressToBytes32(address _address) pure returns (bytes32) {
return bytes32(uint256(uint160(_address)));
}

function bytes32ToAddress(bytes32 _bytes) pure returns (address) {
return address(uint160(uint256(_bytes)));
}
47 changes: 30 additions & 17 deletions evm/test/TokenGatewayTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ contract TokenGatewayTest is BaseTest {
dest: StateMachine.bsc(),
fee: 9 * 1e17, // $0.9
timeout: 0,
to: address(this),
to: addressToBytes32(address(this)),
assetId: keccak256("USD.h"),
data: new bytes(0),
amountInMax: 0
Expand Down Expand Up @@ -55,7 +55,7 @@ contract TokenGatewayTest is BaseTest {
dest: StateMachine.bsc(),
fee: 9 * 1e17, // $0.9
timeout: 0,
to: address(miniStaking),
to: addressToBytes32(address(miniStaking)),
assetId: keccak256("USD.h"),
data: stakeCalldata,
amountInMax: 0
Expand All @@ -78,7 +78,7 @@ contract TokenGatewayTest is BaseTest {
dest: StateMachine.bsc(),
fee: 9 * 1e17, // $0.9
timeout: 0,
to: address(this),
to: addressToBytes32(address(this)),
assetId: keccak256("USD.h"),
data: new bytes(0),
amountInMax: 0
Expand All @@ -91,11 +91,12 @@ contract TokenGatewayTest is BaseTest {

Body memory body = Body({
assetId: keccak256("USD.h"),
to: address(this),
to: addressToBytes32(address(this)),
redeem: false,
amount: 1_000 * 1e18,
from: address(this)
from: addressToBytes32(address(this))
});

vm.prank(address(host));
gateway.onAccept(
PostRequest({
Expand All @@ -119,10 +120,10 @@ contract TokenGatewayTest is BaseTest {

BodyWithCall memory body = BodyWithCall({
assetId: keccak256("USD.h"),
to: address(miniStaking),
to: addressToBytes32(address(miniStaking)),
redeem: false,
amount: 1_000 * 1e18,
from: address(this),
from: addressToBytes32(address(this)),
data: stakeCalldata
});

Expand All @@ -147,10 +148,10 @@ contract TokenGatewayTest is BaseTest {

Body memory body = Body({
assetId: keccak256("USD.h"),
to: address(this),
to: addressToBytes32(address(this)),
redeem: false,
amount: 1_000 * 1e18,
from: address(this)
from: addressToBytes32(address(this))
});
vm.prank(address(host));
gateway.onPostRequestTimeout(
Expand Down Expand Up @@ -321,10 +322,10 @@ contract TokenGatewayTest is BaseTest {
function testOnlyHostCanCallOnAccept() public {
Body memory body = Body({
assetId: keccak256("USD.h"),
to: address(this),
to: addressToBytes32(address(this)),
redeem: false,
amount: 1_000 * 1e18,
from: address(this)
from: addressToBytes32(address(this))
});
vm.expectRevert(bytes("TokenGateway: Unauthorized action"));
gateway.onAccept(
Expand All @@ -343,10 +344,10 @@ contract TokenGatewayTest is BaseTest {
function testWillRejectRequestFromUnkownApplication() public {
Body memory body = Body({
assetId: keccak256("USD.h"),
to: address(this),
to: addressToBytes32(address(this)),
redeem: false,
amount: 1_000 * 1e18,
from: address(this)
from: addressToBytes32(address(this))
});
vm.startPrank(address(host));
vm.expectRevert(bytes("Unauthorized request"));
Expand Down Expand Up @@ -400,10 +401,10 @@ contract TokenGatewayTest is BaseTest {

Body memory redeemBody = Body({
assetId: keccak256("USD.h"),
to: relayer_vault,
to: addressToBytes32(relayer_vault),
redeem: true,
amount: 1_000 * 1e18,
from: address(this)
from: addressToBytes32(address(this))
});

vm.prank(address(host));
Expand Down Expand Up @@ -462,10 +463,10 @@ contract TokenGatewayTest is BaseTest {

Body memory body = Body({
assetId: keccak256("HyperInu.h"),
to: user_vault,
to: addressToBytes32(user_vault),
redeem: false,
amount: 1_000 * 1e18,
from: address(this)
from: addressToBytes32(address(this))
});

uint256 relayerBalanceBefore = hyperInu_h.balanceOf(relayer_address);
Expand Down Expand Up @@ -493,3 +494,15 @@ contract TokenGatewayTest is BaseTest {
assert((relayerBalanceAfter - relayerBalanceBefore) == 1_000 * 1e18); // relayer should have the ERC6160 token
}
}





function addressToBytes32(address _address) pure returns (bytes32) {
return bytes32(uint256(uint160(_address)));
}

function bytes32ToAddress(bytes32 _bytes) pure returns (address) {
return address(uint160(uint256(_bytes)));
}

0 comments on commit 144c652

Please sign in to comment.