ETH Price: $2,029.59 (+0.99%)

Transaction Decoder

Block:
12388598 at May-07-2021 05:53:49 PM +UTC
Transaction Fee:
0.00271081374 ETH $5.50
Gas Used:
26,058 Gas / 104.03 Gwei

Emitted Events:

273 Bridge.Deposit( destination=5A4C043F5460F2BF88C46DC25D5D651C0DB2DD4D3D8B68F6D95B3235BC7CB44A, amount=300000000000000000, token=0x00000000...000000000, sidechainAsset=0000000000000000000000000000000000000000000000000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x1485E985...504f4F602 2,641.231562116090959224 Eth2,641.531562116090959224 Eth0.3
(Ethermine)
1,345.939391779109823836 Eth1,345.942102592849823836 Eth0.00271081374
0xF3Bdb13A...Fc5Cc6658
0.588696852472528655 Eth
Nonce: 35
0.285986038732528655 Eth
Nonce: 36
0.30271081374

Execution Trace

ETH 0.3 Bridge.sendEthToSidechain( to=5A4C043F5460F2BF88C46DC25D5D651C0DB2DD4D3D8B68F6D95B3235BC7CB44A )
{"Bridge.sol":{"content":"pragma solidity ^0.7.4;\n// \"SPDX-License-Identifier: Apache License 2.0\"\n\nimport \"./MasterToken.sol\";\nimport \"./Ownable.sol\";\nimport \"./ERC20Burnable.sol\";\n\n/**\n * Provides functionality of the HASHI bridge\n */\ncontract Bridge {\n    bool internal initialized_;\n    bool internal preparedForMigration_;\n\n    mapping(address =\u003e bool) public isPeer;\n    uint public peersCount;\n\n    /** Substrate proofs used */\n    mapping(bytes32 =\u003e bool) public used;\n    mapping(address =\u003e bool) public _uniqueAddresses;\n\n    /** White list of ERC-20 ethereum native tokens */\n    mapping(address =\u003e bool) public acceptedEthTokens;\n\n    /** White lists of ERC-20 SORA native tokens\n    * We use several representations of the white list for optimisation purposes.\n    */\n    mapping(bytes32 =\u003e address) public _sidechainTokens;\n    mapping(address =\u003e bytes32) public _sidechainTokensByAddress;\n    address[] public _sidechainTokenAddressArray;\n\n    event Withdrawal(bytes32 txHash);\n    event Deposit(bytes32 destination, uint amount, address token, bytes32 sidechainAsset);\n    event ChangePeers(address peerId, bool removal);\n    event PreparedForMigration();\n    event Migrated(address to);\n\n    /**\n     * For XOR and VAL use old token contracts, created for SORA 1 bridge.\n     * Also for XOR and VAL transfers from SORA 2 to Ethereum old bridges will be used.\n     */\n    address public _addressVAL;\n    address public _addressXOR;\n    /** EVM netowrk ID */\n    bytes32 public _networkId;\n\n    /**\n     * Constructor.\n     * @param initialPeers - list of initial bridge validators on substrate side.\n     * @param addressVAL address of VAL token Contract\n     * @param addressXOR address of XOR token Contract\n     * @param networkId id of current EvM network used for bridge purpose.\n     */\n    constructor(\n        address[] memory initialPeers,\n        address addressVAL,\n        address addressXOR,\n        bytes32 networkId)  {\n        for (uint8 i = 0; i \u003c initialPeers.length; i++) {\n            addPeer(initialPeers[i]);\n        }\n        _addressXOR = addressXOR;\n        _addressVAL = addressVAL;\n        _networkId = networkId;\n        initialized_ = true;\n        preparedForMigration_ = false;\n\n        acceptedEthTokens[_addressXOR] = true;\n        acceptedEthTokens[_addressVAL] = true;\n    }\n\n    modifier shouldBeInitialized {\n        require(initialized_ == true, \"Contract should be initialized to use this function\");\n        _;\n    }\n\n    modifier shouldNotBePreparedForMigration {\n        require(preparedForMigration_ == false, \"Contract should not be prepared for migration to use this function\");\n        _;\n    }\n\n    modifier shouldBePreparedForMigration {\n        require(preparedForMigration_ == true, \"Contract should be prepared for migration to use this function\");\n        _;\n    }\n\n    fallback() external {\n        revert();\n    }\n\n    receive() external payable {\n        revert();\n    }\n    \n    /*\n    Used only for migration\n    */\n    function receivePayment() external payable {}\n\n    /**\n     * Adds new token to whitelist.\n     * Token should not been already added.\n     *\n     * @param newToken new token contract address\n     * @param ticker token ticker (symbol)\n     * @param name token title\n     * @param decimals count of token decimal places\n     * @param txHash transaction hash from sidechain\n     * @param v array of signatures of tx_hash (v-component)\n     * @param r array of signatures of tx_hash (r-component)\n     * @param s array of signatures of tx_hash (s-component)\n     */\n    function addEthNativeToken(\n        address newToken,\n        string memory ticker,\n        string memory name,\n        uint8 decimals,\n        bytes32 txHash,\n        uint8[] memory v,\n        bytes32[] memory r,\n        bytes32[] memory s\n    )\n    public shouldBeInitialized {\n        require(used[txHash] == false);\n        require(acceptedEthTokens[newToken] == false);\n        require(checkSignatures(keccak256(abi.encodePacked(newToken, ticker, name, decimals, txHash, _networkId)),\n            v,\n            r,\n            s), \"Peer signatures are invalid\"\n        );\n        acceptedEthTokens[newToken] = true;\n        used[txHash] = true;\n    }\n\n    /**\n     * Preparations for migration to new Bridge contract\n     *\n     * @param thisContractAddress address of this bridge contract\n     * @param salt unique data used for signature\n     * @param v array of signatures of tx_hash (v-component)\n     * @param r array of signatures of tx_hash (r-component)\n     * @param s array of signatures of tx_hash (s-component)\n     */\n    function prepareForMigration(\n        address thisContractAddress,\n        bytes32 salt,\n        uint8[] memory v,\n        bytes32[] memory r,\n        bytes32[] memory s\n    )\n    public\n    shouldBeInitialized shouldNotBePreparedForMigration {\n        require(preparedForMigration_ == false);\n        require(address(this) == thisContractAddress);\n        require(checkSignatures(keccak256(abi.encodePacked(thisContractAddress, salt, _networkId)),\n            v,\n            r,\n            s), \"Peer signatures are invalid\"\n        );\n        preparedForMigration_ = true;\n        emit PreparedForMigration();\n    }\n\n    /**\n    * Shutdown this contract and migrate tokens ownership to the new contract.\n    *\n    * @param thisContractAddress this bridge contract address\n    * @param salt unique data used for signature generation\n    * @param newContractAddress address of the new bridge contract\n    * @param erc20nativeTokens list of ERC20 tokens with non zero balances for this contract. Can be taken from substrate bridge peers.\n    * @param v array of signatures of tx_hash (v-component)\n    * @param r array of signatures of tx_hash (r-component)\n    * @param s array of signatures of tx_hash (s-component)\n    */\n    function shutDownAndMigrate(\n        address thisContractAddress,\n        bytes32 salt,\n        address payable newContractAddress,\n        address[] calldata erc20nativeTokens,\n        uint8[] memory v,\n        bytes32[] memory r,\n        bytes32[] memory s\n    )\n    public\n    shouldBeInitialized shouldBePreparedForMigration {\n        require(address(this) == thisContractAddress);\n        require(checkSignatures(keccak256(abi.encodePacked(thisContractAddress, newContractAddress, salt, erc20nativeTokens, _networkId)),\n            v,\n            r,\n            s), \"Peer signatures are invalid\"\n        );\n        for (uint i = 0; i \u003c _sidechainTokenAddressArray.length; i++) {\n            Ownable token = Ownable(_sidechainTokenAddressArray[i]);\n            token.transferOwnership(newContractAddress);\n        }\n        for (uint i = 0; i \u003c erc20nativeTokens.length; i++) {\n            IERC20 token = IERC20(erc20nativeTokens[i]);\n            token.transfer(newContractAddress, token.balanceOf(address(this)));\n        }\n        Bridge(newContractAddress).receivePayment{value: address(this).balance}();\n        initialized_ = false;\n        emit Migrated(newContractAddress);\n    }\n\n    /**\n    * Add new token from sidechain to the bridge white list.\n    *\n    * @param name token title\n    * @param symbol token symbol\n    * @param decimals number of decimals\n    * @param sidechainAssetId token id on the sidechain\n    * @param txHash sidechain transaction hash\n    * @param v array of signatures of tx_hash (v-component)\n    * @param r array of signatures of tx_hash (r-component)\n    * @param s array of signatures of tx_hash (s-component)\n    */\n    function addNewSidechainToken(\n        string memory name,\n        string memory symbol,\n        uint8 decimals,\n        bytes32 sidechainAssetId,\n        bytes32 txHash,\n        uint8[] memory v,\n        bytes32[] memory r,\n        bytes32[] memory s)\n    public shouldBeInitialized {\n        require(used[txHash] == false);\n        require(checkSignatures(keccak256(abi.encodePacked(\n                name,\n                symbol,\n                decimals,\n                sidechainAssetId,\n                txHash,\n                _networkId\n            )),\n            v,\n            r,\n            s), \"Peer signatures are invalid\"\n        );\n        // Create new instance of the token\n        MasterToken tokenInstance = new MasterToken(name, symbol, decimals, address(this), 0, sidechainAssetId);\n        address tokenAddress = address(tokenInstance);\n        _sidechainTokens[sidechainAssetId] = tokenAddress;\n        _sidechainTokensByAddress[tokenAddress] = sidechainAssetId;\n        _sidechainTokenAddressArray.push(tokenAddress);\n        used[txHash] = true;\n    }\n\n    /**\n    * Send Ethereum to sidechain.\n    *\n    * @param to destionation address on sidechain.\n    */\n    function sendEthToSidechain(\n        bytes32 to\n    )\n    public\n    payable\n    shouldBeInitialized shouldNotBePreparedForMigration {\n        require(msg.value \u003e 0, \"ETH VALUE SHOULD BE MORE THAN 0\");\n        bytes32 empty;\n        emit Deposit(to, msg.value, address(0x0), empty);\n    }\n\n    /**\n     * Send ERC-20 token to sidechain.\n     *\n     * @param to destination address on the sidechain\n     * @param amount amount to sendERC20ToSidechain\n     * @param tokenAddress contract address of token to send\n     */\n    function sendERC20ToSidechain(\n        bytes32 to,\n        uint amount,\n        address tokenAddress)\n    external\n    shouldBeInitialized shouldNotBePreparedForMigration {\n        IERC20 token = IERC20(tokenAddress);\n\n        require(token.allowance(msg.sender, address(this)) \u003e= amount, \"NOT ENOUGH DELEGATED TOKENS ON SENDER BALANCE\");\n\n        bytes32 sidechainAssetId = _sidechainTokensByAddress[tokenAddress];\n        if (sidechainAssetId != \"\" || _addressVAL == tokenAddress || _addressXOR == tokenAddress) {\n            ERC20Burnable mtoken = ERC20Burnable(tokenAddress);\n            mtoken.burnFrom(msg.sender, amount);\n        } else {\n            require(acceptedEthTokens[tokenAddress], \"The Token is not accepted for transfer to sidechain\");\n            token.transferFrom(msg.sender, address(this), amount);\n        }\n        emit Deposit(to, amount, tokenAddress, sidechainAssetId);\n    }\n\n    /**\n     * Add new peer using peers quorum.\n     *\n     * @param newPeerAddress address of the peer to add\n     * @param txHash tx hash from sidechain\n     * @param v array of signatures of tx_hash (v-component)\n     * @param r array of signatures of tx_hash (r-component)\n     * @param s array of signatures of tx_hash (s-component)\n     */\n    function addPeerByPeer(\n        address newPeerAddress,\n        bytes32 txHash,\n        uint8[] memory v,\n        bytes32[] memory r,\n        bytes32[] memory s\n    )\n    public\n    shouldBeInitialized\n    returns (bool)\n    {\n        require(used[txHash] == false);\n        require(checkSignatures(keccak256(abi.encodePacked(newPeerAddress, txHash, _networkId)),\n            v,\n            r,\n            s), \"Peer signatures are invalid\"\n        );\n\n        addPeer(newPeerAddress);\n        used[txHash] = true;\n        emit ChangePeers(newPeerAddress, false);\n        return true;\n    }\n\n    /**\n     * Remove peer using peers quorum.\n     *\n     * @param peerAddress address of the peer to remove\n     * @param txHash tx hash from sidechain\n     * @param v array of signatures of tx_hash (v-component)\n     * @param r array of signatures of tx_hash (r-component)\n     * @param s array of signatures of tx_hash (s-component)\n     */\n    function removePeerByPeer(\n        address peerAddress,\n        bytes32 txHash,\n        uint8[] memory v,\n        bytes32[] memory r,\n        bytes32[] memory s\n    )\n    public\n    shouldBeInitialized\n    returns (bool)\n    {\n        require(used[txHash] == false);\n        require(checkSignatures(\n                keccak256(abi.encodePacked(peerAddress, txHash, _networkId)),\n                v,\n                r,\n                s), \"Peer signatures are invalid\"\n        );\n\n        removePeer(peerAddress);\n        used[txHash] = true;\n        emit ChangePeers(peerAddress, true);\n        return true;\n    }\n\n    /**\n     * Withdraws specified amount of ether or one of ERC-20 tokens to provided sidechain address\n     * @param tokenAddress address of token to withdraw (0 for ether)\n     * @param amount amount of tokens or ether to withdraw\n     * @param to target account address\n     * @param txHash hash of transaction from sidechain\n     * @param from source of transfer\n     * @param v array of signatures of tx_hash (v-component)\n     * @param r array of signatures of tx_hash (r-component)\n     * @param s array of signatures of tx_hash (s-component)\n     */\n    function receiveByEthereumAssetAddress(\n        address tokenAddress,\n        uint256 amount,\n        address payable to,\n        address from,\n        bytes32 txHash,\n        uint8[] memory v,\n        bytes32[] memory r,\n        bytes32[] memory s\n    )\n    public shouldBeInitialized\n    {\n        require(used[txHash] == false);\n        require(checkSignatures(\n                keccak256(abi.encodePacked(tokenAddress, amount, to, from, txHash, _networkId)),\n                v,\n                r,\n                s), \"Peer signatures are invalid\"\n        );\n\n        if (tokenAddress == address(0)) {\n            used[txHash] = true;\n            // untrusted transfer, relies on provided cryptographic proof\n            to.transfer(amount);\n        } else {\n            IERC20 coin = IERC20(tokenAddress);\n            used[txHash] = true;\n            // untrusted call, relies on provided cryptographic proof\n            coin.transfer(to, amount);\n        }\n        emit Withdrawal(txHash);\n    }\n\n    /**\n     * Mint new Token\n     * @param sidechainAssetId id of sidechainToken to mint\n     * @param amount how much to mint\n     * @param to destination address\n     * @param from sender address\n     * @param txHash hash of transaction from Iroha\n     * @param v array of signatures of tx_hash (v-component)\n     * @param r array of signatures of tx_hash (r-component)\n     * @param s array of signatures of tx_hash (s-component)\n     */\n    function receiveBySidechainAssetId(\n        bytes32 sidechainAssetId,\n        uint256 amount,\n        address to,\n        address from,\n        bytes32 txHash,\n        uint8[] memory v,\n        bytes32[] memory r,\n        bytes32[] memory s\n    )\n    public shouldBeInitialized\n    {\n        require(_sidechainTokens[sidechainAssetId] != address(0x0), \"Sidechain asset is not registered\");\n        require(used[txHash] == false);\n        require(checkSignatures(\n                keccak256(abi.encodePacked(sidechainAssetId, amount, to, from, txHash, _networkId)),\n                v,\n                r,\n                s), \"Peer signatures are invalid\"\n        );\n\n        MasterToken tokenInstance = MasterToken(_sidechainTokens[sidechainAssetId]);\n        tokenInstance.mintTokens(to, amount);\n        used[txHash] = true;\n        emit Withdrawal(txHash);\n    }\n\n    /**\n     * Checks given addresses for duplicates and if they are peers signatures\n     * @param hash unsigned data\n     * @param v v-component of signature from hash\n     * @param r r-component of signature from hash\n     * @param s s-component of signature from hash\n     * @return true if all given addresses are correct or false otherwise\n     */\n    function checkSignatures(bytes32 hash,\n        uint8[] memory v,\n        bytes32[] memory r,\n        bytes32[] memory s\n    )\n    private\n    returns (bool) {\n        require(peersCount \u003e= 1);\n        require(v.length == r.length);\n        require(r.length == s.length);\n        uint needSigs = peersCount - (peersCount - 1) / 3;\n        require(s.length \u003e= needSigs);\n\n        uint count = 0;\n        address[] memory recoveredAddresses = new address[](s.length);\n        for (uint i = 0; i \u003c s.length; ++i) {\n            address recoveredAddress = recoverAddress(\n                hash,\n                v[i],\n                r[i],\n                s[i]\n            );\n\n            // not a peer address or not unique\n            if (isPeer[recoveredAddress] != true || _uniqueAddresses[recoveredAddress] == true) {\n                continue;\n            }\n            recoveredAddresses[count] = recoveredAddress;\n            count = count + 1;\n            _uniqueAddresses[recoveredAddress] = true;\n        }\n\n        // restore state for future usages\n        for (uint i = 0; i \u003c count; ++i) {\n            _uniqueAddresses[recoveredAddresses[i]] = false;\n        }\n\n        return count \u003e= needSigs;\n    }\n\n    /**\n     * Recovers address from a given single signature\n     * @param hash unsigned data\n     * @param v v-component of signature from hash\n     * @param r r-component of signature from hash\n     * @param s s-component of signature from hash\n     * @return address recovered from signature\n     */\n    function recoverAddress(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s)\n    private\n    pure\n    returns (address) {\n        bytes32 simple_hash = keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n        address res = ecrecover(simple_hash, v, r, s);\n        return res;\n    }\n\n    /**\n     * Adds new peer to list of signature verifiers.\n     * Internal function\n     * @param newAddress address of new peer\n     */\n    function addPeer(address newAddress)\n    internal\n    returns (uint) {\n        require(isPeer[newAddress] == false);\n        isPeer[newAddress] = true;\n        ++peersCount;\n        return peersCount;\n    }\n\n    function removePeer(address peerAddress)\n    internal {\n        require(isPeer[peerAddress] == true);\n        isPeer[peerAddress] = false;\n        --peersCount;\n    }\n}"},"ERC20.sol":{"content":"pragma solidity ^0.7.4;\n// \"SPDX-License-Identifier: Apache License 2.0\"\n\nimport \"./IERC20.sol\";\nimport \"./SafeMath.sol\";\n\n/**\n * @title Standard ERC20 token\n *\n * @dev Implementation of the basic standard token.\n * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md\n * Originally based on code by FirstBlood:\n * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol\n *\n * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for\n * all accounts just by listening to said events. Note that this isn\u0027t required by the specification, and other\n * compliant implementations may not do it.\n */\ncontract ERC20 is IERC20 {\n    using SafeMath for uint256;\n\n    mapping(address =\u003e uint256) private _balances;\n\n    mapping(address =\u003e mapping(address =\u003e uint256)) private _allowed;\n\n    uint256 private _totalSupply;\n\n    /**\n    * @dev Total number of tokens in existence\n    */\n    function totalSupply() public view override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n    * @dev Gets the balance of the specified address.\n    * @param owner The address to query the balance of.\n    * @return An uint256 representing the amount owned by the passed address.\n    */\n    function balanceOf(address owner) public view override returns (uint256) {\n        return _balances[owner];\n    }\n\n    /**\n     * @dev Function to check the amount of tokens that an owner allowed to a spender.\n     * @param owner address The address which owns the funds.\n     * @param spender address The address which will spend the funds.\n     * @return A uint256 specifying the amount of tokens still available for the spender.\n     */\n    function allowance(address owner, address spender) public view override returns (uint256) {\n        return _allowed[owner][spender];\n    }\n\n    /**\n    * @dev Transfer token for a specified address\n    * @param to The address to transfer to.\n    * @param value The amount to be transferred.\n    */\n    function transfer(address to, uint256 value) public override returns (bool) {\n        _transfer(msg.sender, to, value);\n        return true;\n    }\n\n    /**\n     * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.\n     * Beware that changing an allowance with this method brings the risk that someone may use both the old\n     * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this\n     * race condition is to first reduce the spender\u0027s allowance to 0 and set the desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     */\n    function approve(address spender, uint256 value) public override returns (bool) {\n        _approve(msg.sender, spender, value);\n        return true;\n    }\n\n    /**\n     * @dev Transfer tokens from one address to another.\n     * Note that while this function emits an Approval event, this is not required as per the specification,\n     * and other compliant implementations may not emit the event.\n     * @param from address The address which you want to send tokens from\n     * @param to address The address which you want to transfer to\n     * @param value uint256 the amount of tokens to be transferred\n     */\n    function transferFrom(address from, address to, uint256 value) public override returns (bool) {\n        _transfer(from, to, value);\n        _approve(from, msg.sender, _allowed[from][msg.sender].sub(value));\n        return true;\n    }\n\n    /**\n     * @dev Increase the amount of tokens that an owner allowed to a spender.\n     * approve should be called when allowed_[_spender] == 0. To increment\n     * allowed value is better to use this function to avoid 2 calls (and wait until\n     * the first transaction is mined)\n     * From MonolithDAO Token.sol\n     * Emits an Approval event.\n     * @param spender The address which will spend the funds.\n     * @param addedValue The amount of tokens to increase the allowance by.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {\n        _approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue));\n        return true;\n    }\n\n    /**\n     * @dev Decrease the amount of tokens that an owner allowed to a spender.\n     * approve should be called when allowed_[_spender] == 0. To decrement\n     * allowed value is better to use this function to avoid 2 calls (and wait until\n     * the first transaction is mined)\n     * From MonolithDAO Token.sol\n     * Emits an Approval event.\n     * @param spender The address which will spend the funds.\n     * @param subtractedValue The amount of tokens to decrease the allowance by.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {\n        _approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue));\n        return true;\n    }\n\n    /**\n    * @dev Transfer token for a specified addresses\n    * @param from The address to transfer from.\n    * @param to The address to transfer to.\n    * @param value The amount to be transferred.\n    */\n    function _transfer(address from, address to, uint256 value) internal {\n        require(to != address(0));\n\n        _balances[from] = _balances[from].sub(value);\n        _balances[to] = _balances[to].add(value);\n        emit Transfer(from, to, value);\n    }\n\n    /**\n     * @dev Internal function that mints an amount of the token and assigns it to\n     * an account. This encapsulates the modification of balances such that the\n     * proper events are emitted.\n     * @param account The account that will receive the created tokens.\n     * @param value The amount that will be created.\n     */\n    function _mint(address account, uint256 value) internal {\n        require(account != address(0));\n\n        _totalSupply = _totalSupply.add(value);\n        _balances[account] = _balances[account].add(value);\n        emit Transfer(address(0), account, value);\n    }\n\n    /**\n     * @dev Internal function that burns an amount of the token of a given\n     * account.\n     * @param account The account whose tokens will be burnt.\n     * @param value The amount that will be burnt.\n     */\n    function _burn(address account, uint256 value) internal {\n        require(account != address(0));\n\n        _totalSupply = _totalSupply.sub(value);\n        _balances[account] = _balances[account].sub(value);\n        emit Transfer(account, address(0), value);\n    }\n\n    /**\n     * @dev Approve an address to spend another addresses\u0027 tokens.\n     * @param owner The address that owns the tokens.\n     * @param spender The address that will spend the tokens.\n     * @param value The number of tokens that can be spent.\n     */\n    function _approve(address owner, address spender, uint256 value) internal {\n        require(spender != address(0));\n        require(owner != address(0));\n\n        _allowed[owner][spender] = value;\n        emit Approval(owner, spender, value);\n    }\n\n    /**\n     * @dev Internal function that burns an amount of the token of a given\n     * account, deducting from the sender\u0027s allowance for said account. Uses the\n     * internal burn function.\n     * Emits an Approval event (reflecting the reduced allowance).\n     * @param account The account whose tokens will be burnt.\n     * @param value The amount that will be burnt.\n     */\n    function _burnFrom(address account, uint256 value) internal {\n        _burn(account, value);\n        _approve(account, msg.sender, _allowed[account][msg.sender].sub(value));\n    }\n}"},"ERC20Burnable.sol":{"content":"pragma solidity ^0.7.4;\n// \"SPDX-License-Identifier: Apache License 2.0\"\n\nimport \"./ERC20.sol\";\n\n/**\n * @title Burnable Token\n * @dev Token that can be irreversibly burned (destroyed).\n */\ncontract ERC20Burnable is ERC20 {\n    /**\n     * @dev Burns a specific amount of tokens.\n     * @param value The amount of token to be burned.\n     */\n    function burn(uint256 value) public {\n        _burn(msg.sender, value);\n    }\n\n    /**\n     * @dev Burns a specific amount of tokens from the target address and decrements allowance\n     * @param from address The address which you want to send tokens from\n     * @param value uint256 The amount of token to be burned\n     */\n    function burnFrom(address from, uint256 value) public {\n        _burnFrom(from, value);\n    }\n}"},"ERC20Detailed.sol":{"content":"pragma solidity ^0.7.4;\n// \"SPDX-License-Identifier: Apache License 2.0\"\n\nimport \"./IERC20.sol\";\n\n/**\n * @title ERC20Detailed token\n * @dev The decimals are only for visualization purposes.\n * All the operations are done using the smallest and indivisible token unit,\n * just as on Ethereum all the operations are done in wei.\n */\nabstract contract ERC20Detailed is IERC20 {\n    string private _name;\n    string private _symbol;\n    uint8 private _decimals;\n\n    constructor (\n        string memory name_, \n        string memory symbol_, \n        uint8 decimals_) {\n        _name = name_;\n        _symbol = symbol_;\n        _decimals = decimals_;\n    } \n\n    /**\n     * @return the name of the token.\n     */\n    function name() public view returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @return the symbol of the token.\n     */\n    function symbol() public view returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @return the number of decimals of the token.\n     */\n    function decimals() public view returns (uint8) {\n        return _decimals;\n    }\n}"},"IERC20.sol":{"content":"pragma solidity ^0.7.4;\n// \"SPDX-License-Identifier: MIT\"\n\ninterface IERC20 {\n    function totalSupply() external view returns (uint256);\n    function balanceOf(address account) external view returns (uint256);\n    function allowance(address owner, address spender) external view returns (uint256);\n    function transfer(address recipient, uint256 amount) external returns (bool);\n    function approve(address spender, uint256 amount) external returns (bool);\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n    event Transfer(address indexed from, address indexed to, uint256 value);\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}"},"MasterToken.sol":{"content":"pragma solidity ^0.7.4;\n// \"SPDX-License-Identifier: Apache License 2.0\"\n\nimport \"./ERC20Detailed.sol\";\nimport \"./ERC20Burnable.sol\";\nimport \"./Ownable.sol\";\n\ncontract MasterToken is ERC20Burnable, ERC20Detailed, Ownable {\n\n    bytes32 public _sidechainAssetId;\n\n    /**\n     * @dev Constructor that gives the specified address all of existing tokens.\n     */\n    constructor(\n        string memory name, \n        string memory symbol, \n        uint8 decimals, \n        address beneficiary, \n        uint256 supply,\n        bytes32 sidechainAssetId) \n        ERC20Detailed(name, symbol, decimals) {\n        _sidechainAssetId = sidechainAssetId;    \n        _mint(beneficiary, supply);\n        \n    }\n    \n    fallback() external {\n        revert();\n    }\n\n    function mintTokens(address beneficiary, uint256 amount) public onlyOwner {\n        _mint(beneficiary, amount);\n    }\n\n}"},"Ownable.sol":{"content":"pragma solidity ^0.7.4;\n// \"SPDX-License-Identifier: Apache License 2.0\"\n\n/**\n * @title Ownable\n * @dev The Ownable contract has an owner address, and provides basic authorization control\n * functions, this simplifies the implementation of \"user permissions\".\n */\nabstract contract Ownable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev The Ownable constructor sets the original `owner` of the contract to the sender\n     * account.\n     */\n    constructor () {\n        _owner = msg.sender;\n        emit OwnershipTransferred(address(0), _owner);\n    }\n\n    /**\n     * @return the address of the owner.\n     */\n    function owner() public view returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(isOwner());\n        _;\n    }\n\n    /**\n     * @return true if `msg.sender` is the owner of the contract.\n     */\n    function isOwner() public view returns (bool) {\n        return msg.sender == _owner;\n    }\n\n    /**\n     * @dev Allows the current owner to relinquish control of the contract.\n     * @notice Renouncing to ownership will leave the contract without an owner.\n     * It will not be possible to call the functions with the `onlyOwner`\n     * modifier anymore.\n     */\n    function renounceOwnership() public onlyOwner {\n        emit OwnershipTransferred(_owner, address(0));\n        _owner = address(0);\n    }\n\n    /**\n     * @dev Allows the current owner to transfer control of the contract to a newOwner.\n     * @param newOwner The address to transfer ownership to.\n     */\n    function transferOwnership(address newOwner) public onlyOwner {\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers control of the contract to a newOwner.\n     * @param newOwner The address to transfer ownership to.\n     */\n    function _transferOwnership(address newOwner) internal {\n        require(newOwner != address(0));\n        emit OwnershipTransferred(_owner, newOwner);\n        _owner = newOwner;\n    }\n}"},"SafeMath.sol":{"content":"pragma solidity ^0.7.4;\n// \"SPDX-License-Identifier: Apache License 2.0\"\n\n\n/**\n * @dev Wrappers over Solidity\u0027s arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it\u0027s recommended to use it always.\n */\nlibrary SafeMath {\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity\u0027s `+` operator.\n     *\n     * Requirements:\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        uint256 c = a + b;\n        require(c \u003e= a, \"SafeMath: addition overflow\");\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity\u0027s `-` operator.\n     *\n     * Requirements:\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        return sub(a, b, \"SafeMath: subtraction overflow\");\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity\u0027s `-` operator.\n     *\n     * Requirements:\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b \u003c= a, errorMessage);\n        uint256 c = a - b;\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity\u0027s `*` operator.\n     *\n     * Requirements:\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        // Gas optimization: this is cheaper than requiring \u0027a\u0027 not being zero, but the\n        // benefit is lost if \u0027b\u0027 is also tested.\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n        if (a == 0) {\n            return 0;\n        }\n\n        uint256 c = a * b;\n        require(c / a == b, \"SafeMath: multiplication overflow\");\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers. Reverts on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity\u0027s `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        return div(a, b, \"SafeMath: division by zero\");\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity\u0027s `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        // Solidity only automatically asserts when dividing by 0\n        require(b \u003e 0, errorMessage);\n        uint256 c = a / b;\n        // assert(a == b * c + a % b); // There is no case in which this doesn\u0027t hold\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * Reverts when dividing by zero.\n     *\n     * Counterpart to Solidity\u0027s `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        return mod(a, b, \"SafeMath: modulo by zero\");\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * Reverts with custom message when dividing by zero.\n     *\n     * Counterpart to Solidity\u0027s `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b != 0, errorMessage);\n        return a % b;\n    }\n}"}}