76 lines
3.0 KiB
Solidity
76 lines
3.0 KiB
Solidity
// SPDX-License-Identifier: UNLICENSED
|
|
pragma solidity ^0.8.13;
|
|
|
|
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
import "./Wormhole/IWormhole.sol";
|
|
import "./Wormhole/ITokenBridge.sol";
|
|
import "./Wormhole/BridgeStructs.sol";
|
|
import "solidity-bytes-utils/BytesLib.sol";
|
|
|
|
contract Xmint is ERC20 {
|
|
using BytesLib for bytes;
|
|
|
|
mapping(uint16 => bytes32) _applicationContracts;
|
|
mapping(bytes32 => bool) _completedMessages;
|
|
address owner;
|
|
IWormhole core_bridge;
|
|
ITokenBridge token_bridge;
|
|
uint32 nonce = 0;
|
|
event Log(string indexed str);
|
|
|
|
constructor(
|
|
string memory name_,
|
|
string memory symbol_,
|
|
address coreBridgeAddress,
|
|
address tokenBridgeAddress
|
|
) ERC20(name_, symbol_) {
|
|
owner = msg.sender;
|
|
core_bridge = IWormhole(coreBridgeAddress);
|
|
token_bridge = ITokenBridge(tokenBridgeAddress);
|
|
}
|
|
|
|
/**
|
|
Registers it's sibling applications on other chains as the only ones that can send this instance messages
|
|
*/
|
|
function registerApplicationContracts(uint16 chainId, bytes32 applicationAddr) public {
|
|
require(msg.sender == owner, "Only owner can register new chains!");
|
|
_applicationContracts[chainId] = applicationAddr;
|
|
}
|
|
|
|
/**
|
|
Takes inventory of the foreign currency
|
|
Mints tokens to self
|
|
Transfers tokens with Payload 1 to Receipient on Foreign chain
|
|
*/
|
|
function submitForeignPurchase(bytes memory encodedVm) public returns (uint64) {
|
|
// Complete transfer will give the Tokens to this Contract
|
|
BridgeStructs.TransferWithPayload memory vaa = _decodePayload(token_bridge.completeTransferWithPayload(encodedVm));
|
|
// Mint tokens to this contract
|
|
//amt they paid is NATIVE
|
|
//multiply by 100 to get how many tokens to give out
|
|
uint256 amtToMint = vaa.amount * 100;
|
|
_mint(address(this), amtToMint);
|
|
// Give Token Bridge allowance to take tokens from this contract
|
|
this.approve(address(token_bridge), amtToMint);
|
|
// Transfer tokens via Token Bridge over to Recipient in payload
|
|
uint64 sequence = token_bridge.transferTokens(address(this), amtToMint, vaa.tokenChain, bytes32(vaa.payload), 0, nonce);
|
|
nonce += 1;
|
|
return sequence;
|
|
}
|
|
|
|
function _decodePayload(bytes memory payload) internal pure returns (BridgeStructs.TransferWithPayload memory) {
|
|
BridgeStructs.TransferWithPayload memory decoded = BridgeStructs.TransferWithPayload({
|
|
payloadID: payload.slice(0,1).toUint8(0),
|
|
amount: payload.slice(1,32).toUint256(0),
|
|
tokenAddress: payload.slice(33,32).toBytes32(0),
|
|
tokenChain: payload.slice(65,2).toUint16(0),
|
|
to: payload.slice(67,32).toBytes32(0),
|
|
toChain: payload.slice(99,2).toUint16(0),
|
|
fromAddress: payload.slice(101,32).toBytes32(0),
|
|
payload: payload.slice(133, payload.length-133)
|
|
});
|
|
|
|
return decoded;
|
|
}
|
|
}
|