Solidity Smart Contract

Overview

The Solidity Smart Contracts represent the bridge on the EVM compatible blockchains such as BSC, Ethereum & HECO.

  1. XPNet.sol - is the ERC-1155 Smart Contract

  2. Minter.sol - is responsible for the rest of the multibridge-related functionality.

1. XPNet.sol - ERC-1155

The smart contract declaration

contract XPNet is ERC1155, Ownable { ... }

1. Minting

function mint(address to, uint256 id, uint256 amount) public onlyOwner {
    _mint(to, id, amount, "");
}

2. Burning

function burn(address from, uint256 id, uint256 amount) public onlyOwner {
		_burn(from, id, amount);
}

2. Minter.sol - the bridge smart contract

The contract declaration & local variables

contract Minter { 
  uint256 private threshold;         // BFT threshold
	uint256 private action_cnt = 0;		 // Action counter
	uint256 private nft_cnt = 0x10000; // reserve 0 - 0xffff for chain liquidity
	XPNet   private token;						 // XPNET token
}

1. Events emitted by the SC for the bridge relay validators

event Transfer(
    uint256 action_id, 
    uint64 chain_nonce, 
    string to, 
    uint256 value); // Transfer ETH to XP.network
    
event TransferErc721(
    uint256 action_id, 
    uint64 chain_nonce, 
    string to, 
    string data); // Transfer Erc721 to XP.network
    
event TransferErc1155(
    uint256 action_id, 
    uint64 chain_nonce, 
    string to, 
    uint256 id, 
    address contract_addr); // Transfer Erc1155 to XP.network
    
event Unfreeze(
    uint256 action_id, 
    uint64 chain_nonce, 
    string to, 
    uint256 value); // Unfreeze XPNET on XP.network
    
event UnfreezeNft(
    uint256 action_id, 
    string to, 
    string data); // Unfreeze NFT on XP.network

2. Validators mapper

mapping (uint128=>ActionInfo) private actions;
mapping (uint128=>mapping (address=>uint8)) private action_validators;

3. Transfering fungible tokens

function validate_transfer(
		uint128 action_id, 
		uint64 chain_nonce, 
		address to, 
		uint256 value
		) public {
				ValidationRes res = validate_action(action_id, Action.Transfer);
				if (res == ValidationRes.Execute) {
					token.mint(to, chain_nonce, value);
				}
}

4. Transfering NFTs

function validate_transfer_nft(
	uint128 action_id, 
	address to, 
	string calldata data
	) public {
		ValidationRes res = validate_action(action_id, Action.TransferUnique);
		if (res == ValidationRes.Execute) {
			token.mint(to, nft_cnt, 1);
			nft_cnt += 1;
			token.setURI(nft_cnt, data);
		}
	}

5. Releasing the wrapped tokens to an account in the local blockchain

function validate_unfreeze(
	uint128 action_id, 
	address payable to, 
	uint256 value
	) public {
			ValidationRes res = validate_action(action_id, Action.Unfreeze);
			if (res == ValidationRes.Execute) {
				require(to.send(value), "FAILED TO TRANSFER?!");
		}
	}

6. Sending wrapped tokens to a target blockchain

function withdraw(
		string memory to, 
		uint64 chain_nonce, 
		uint256 value
		) public {
				token.burn(msg.sender, chain_nonce, value);
				emit Unfreeze(action_cnt, chain_nonce, to, value);
				action_cnt += 1;
	}

7. Sending wrapped NFT to a target blockchain

function withdraw_nft(
		string calldata to, 
		uint256 id
		) public {
				string memory data = token.uri(id);

				token.burn(msg.sender, id, 1);
				token.setURI(id, "");
				emit UnfreezeNft(action_cnt, to, data);
				action_cnt += 1;
	}

8. Locking a native token & sending its wrapped quantity to a target blockchain

function freeze(uint64 chain_nonce, string memory to) public payable {
		require(msg.value > 0, "value must be > 0!");
		emit Transfer(action_cnt, chain_nonce, to, msg.value);
		action_cnt += 1;
}

Last updated

Was this helpful?