Contract 0x525127c1f5670cc102b26905dccf8245c05c164f

Txn Hash Method
Block
From
To
Value [Txn Fee]
0x7cb06df2776084f2a5091f1884aaf3edba48ce0227846bd05a54ecd1c7bb718a0x60806040183973602021-10-03 17:57:40483 days 4 hrs agoMoons: Deployer IN  Create: HomeAMB0 xDAI0.135616692
[ Download CSV Export 
View more zero value Internal Transactions in Advanced View mode
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
HomeAMB

Compiler Version
v0.4.24+commit.e67f0147

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at gnosisscan.io on 2022-08-04
*/

// File: contracts/interfaces/IAMBInformationReceiver.sol

pragma solidity 0.4.24;

interface IAMBInformationReceiver {
    function onInformationReceived(bytes32 messageId, bool status, bytes result) external;
}

// File: contracts/interfaces/IBridgeValidators.sol

pragma solidity 0.4.24;

interface IBridgeValidators {
    function isValidator(address _validator) external view returns (bool);
    function requiredSignatures() external view returns (uint256);
    function owner() external view returns (address);
}

// File: contracts/libraries/Message.sol

pragma solidity 0.4.24;


library Message {
    function addressArrayContains(address[] array, address value) internal pure returns (bool) {
        for (uint256 i = 0; i < array.length; i++) {
            if (array[i] == value) {
                return true;
            }
        }
        return false;
    }
    // layout of message :: bytes:
    // offset  0: 32 bytes :: uint256 - message length
    // offset 32: 20 bytes :: address - recipient address
    // offset 52: 32 bytes :: uint256 - value
    // offset 84: 32 bytes :: bytes32 - transaction hash
    // offset 116: 20 bytes :: address - contract address to prevent double spending

    // mload always reads 32 bytes.
    // so we can and have to start reading recipient at offset 20 instead of 32.
    // if we were to read at 32 the address would contain part of value and be corrupted.
    // when reading from offset 20 mload will read 12 bytes (most of them zeros) followed
    // by the 20 recipient address bytes and correctly convert it into an address.
    // this saves some storage/gas over the alternative solution
    // which is padding address to 32 bytes and reading recipient at offset 32.
    // for more details see discussion in:
    // https://github.com/paritytech/parity-bridge/issues/61
    function parseMessage(bytes message)
        internal
        pure
        returns (address recipient, uint256 amount, bytes32 txHash, address contractAddress)
    {
        require(isMessageValid(message));
        assembly {
            recipient := mload(add(message, 20))
            amount := mload(add(message, 52))
            txHash := mload(add(message, 84))
            contractAddress := mload(add(message, 104))
        }
    }

    function isMessageValid(bytes _msg) internal pure returns (bool) {
        return _msg.length == requiredMessageLength();
    }

    function requiredMessageLength() internal pure returns (uint256) {
        return 104;
    }

    function recoverAddressFromSignedMessage(bytes signature, bytes message, bool isAMBMessage)
        internal
        pure
        returns (address)
    {
        require(signature.length == 65);
        bytes32 r;
        bytes32 s;
        bytes1 v;

        assembly {
            r := mload(add(signature, 0x20))
            s := mload(add(signature, 0x40))
            v := mload(add(signature, 0x60))
        }
        require(uint8(v) == 27 || uint8(v) == 28);
        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0);

        return ecrecover(hashMessage(message, isAMBMessage), uint8(v), r, s);
    }

    function hashMessage(bytes message, bool isAMBMessage) internal pure returns (bytes32) {
        bytes memory prefix = "\x19Ethereum Signed Message:\n";
        if (isAMBMessage) {
            return keccak256(abi.encodePacked(prefix, uintToString(message.length), message));
        } else {
            string memory msgLength = "104";
            return keccak256(abi.encodePacked(prefix, msgLength, message));
        }
    }

    /**
    * @dev Validates provided signatures, only first requiredSignatures() number
    * of signatures are going to be validated, these signatures should be from different validators.
    * @param _message bytes message used to generate signatures
    * @param _signatures bytes blob with signatures to be validated.
    * First byte X is a number of signatures in a blob,
    * next X bytes are v components of signatures,
    * next 32 * X bytes are r components of signatures,
    * next 32 * X bytes are s components of signatures.
    * @param _validatorContract contract, which conforms to the IBridgeValidators interface,
    * where info about current validators and required signatures is stored.
    * @param isAMBMessage true if _message is an AMB message with arbitrary length.
    */
    function hasEnoughValidSignatures(
        bytes _message,
        bytes _signatures,
        IBridgeValidators _validatorContract,
        bool isAMBMessage
    ) internal view {
        require(isAMBMessage || isMessageValid(_message));
        uint256 requiredSignatures = _validatorContract.requiredSignatures();
        uint256 amount;
        assembly {
            amount := and(mload(add(_signatures, 1)), 0xff)
        }
        require(amount >= requiredSignatures);
        bytes32 hash = hashMessage(_message, isAMBMessage);
        address[] memory encounteredAddresses = new address[](requiredSignatures);

        for (uint256 i = 0; i < requiredSignatures; i++) {
            uint8 v;
            bytes32 r;
            bytes32 s;
            uint256 posr = 33 + amount + 32 * i;
            uint256 poss = posr + 32 * amount;
            assembly {
                v := mload(add(_signatures, add(2, i)))
                r := mload(add(_signatures, posr))
                s := mload(add(_signatures, poss))
            }

            address recoveredAddress = ecrecover(hash, v, r, s);
            require(_validatorContract.isValidator(recoveredAddress));
            require(!addressArrayContains(encounteredAddresses, recoveredAddress));
            encounteredAddresses[i] = recoveredAddress;
        }
    }

    function uintToString(uint256 i) internal pure returns (string) {
        if (i == 0) return "0";
        uint256 j = i;
        uint256 length;
        while (j != 0) {
            length++;
            j /= 10;
        }
        bytes memory bstr = new bytes(length);
        uint256 k = length - 1;
        while (i != 0) {
            bstr[k--] = bytes1(48 + (i % 10));
            i /= 10;
        }
        return string(bstr);
    }
}

// File: contracts/libraries/ArbitraryMessage.sol

pragma solidity 0.4.24;

library ArbitraryMessage {
    /**
    * @dev Unpacks data fields from AMB message
    * layout of message :: bytes:
    * offset  0              : 32 bytes :: uint256 - message length
    * offset 32              : 32 bytes :: bytes32 - messageId
    * offset 64              : 20 bytes :: address - sender address
    * offset 84              : 20 bytes :: address - executor contract
    * offset 104             : 4 bytes  :: uint32  - gasLimit
    * offset 108             : 1 bytes  :: uint8   - source chain id length (X)
    * offset 109             : 1 bytes  :: uint8   - destination chain id length (Y)
    * offset 110             : 1 bytes  :: uint8   - dataType
    * offset 111             : X bytes  :: bytes   - source chain id
    * offset 111 + X         : Y bytes  :: bytes   - destination chain id

    * NOTE: when message structure is changed, make sure that MESSAGE_PACKING_VERSION from VersionableAMB is updated as well
    * NOTE: assembly code uses calldatacopy, make sure that message is passed as the first argument in the calldata
    * @param _data encoded message
    */
    function unpackData(bytes _data)
        internal
        pure
        returns (
            bytes32 messageId,
            address sender,
            address executor,
            uint32 gasLimit,
            uint8 dataType,
            uint256[2] chainIds,
            bytes memory data
        )
    {
        // 32 (message id) + 20 (sender) + 20 (executor) + 4 (gasLimit) + 1 (source chain id length) + 1 (destination chain id length) + 1 (dataType)
        uint256 srcdataptr = 32 + 20 + 20 + 4 + 1 + 1 + 1;
        uint256 datasize;

        assembly {
            messageId := mload(add(_data, 32)) // 32 bytes
            sender := and(mload(add(_data, 52)), 0xffffffffffffffffffffffffffffffffffffffff) // 20 bytes

            // executor (20 bytes) + gasLimit (4 bytes) + srcChainIdLength (1 byte) + dstChainIdLength (1 bytes) + dataType (1 byte) + remainder (5 bytes)
            let blob := mload(add(_data, 84))

            // after bit shift left 12 bytes are zeros automatically
            executor := shr(96, blob)
            gasLimit := and(shr(64, blob), 0xffffffff)

            dataType := byte(26, blob)

            // load source chain id length
            let chainIdLength := byte(24, blob)

            // at this moment srcdataptr points to sourceChainId

            // mask for sourceChainId
            // e.g. length X -> (1 << (X * 8)) - 1
            let mask := sub(shl(shl(3, chainIdLength), 1), 1)

            // increase payload offset by length of source chain id
            srcdataptr := add(srcdataptr, chainIdLength)

            // write sourceChainId
            mstore(chainIds, and(mload(add(_data, srcdataptr)), mask))

            // at this moment srcdataptr points to destinationChainId

            // load destination chain id length
            chainIdLength := byte(25, blob)

            // mask for destinationChainId
            // e.g. length X -> (1 << (X * 8)) - 1
            mask := sub(shl(shl(3, chainIdLength), 1), 1)

            // increase payload offset by length of destination chain id
            srcdataptr := add(srcdataptr, chainIdLength)

            // write destinationChainId
            mstore(add(chainIds, 32), and(mload(add(_data, srcdataptr)), mask))

            // at this moment srcdataptr points to payload

            // datasize = message length - payload offset
            datasize := sub(mload(_data), srcdataptr)
        }

        data = new bytes(datasize);
        assembly {
            // 36 = 4 (selector) + 32 (bytes length header)
            srcdataptr := add(srcdataptr, 36)

            // calldataload(4) - offset of first bytes argument in the calldata
            calldatacopy(add(data, 32), add(calldataload(4), srcdataptr), datasize)
        }
    }
}

// File: contracts/interfaces/IUpgradeabilityOwnerStorage.sol

pragma solidity 0.4.24;

interface IUpgradeabilityOwnerStorage {
    function upgradeabilityOwner() external view returns (address);
}

// File: contracts/upgradeable_contracts/Upgradeable.sol

pragma solidity 0.4.24;


contract Upgradeable {
    // Avoid using onlyUpgradeabilityOwner name to prevent issues with implementation from proxy contract
    modifier onlyIfUpgradeabilityOwner() {
        require(msg.sender == IUpgradeabilityOwnerStorage(this).upgradeabilityOwner());
        /* solcov ignore next */
        _;
    }
}

// File: contracts/upgradeability/EternalStorage.sol

pragma solidity 0.4.24;

/**
 * @title EternalStorage
 * @dev This contract holds all the necessary state variables to carry out the storage of any contract.
 */
contract EternalStorage {
    mapping(bytes32 => uint256) internal uintStorage;
    mapping(bytes32 => string) internal stringStorage;
    mapping(bytes32 => address) internal addressStorage;
    mapping(bytes32 => bytes) internal bytesStorage;
    mapping(bytes32 => bool) internal boolStorage;
    mapping(bytes32 => int256) internal intStorage;

}

// File: contracts/upgradeable_contracts/Initializable.sol

pragma solidity 0.4.24;


contract Initializable is EternalStorage {
    bytes32 internal constant INITIALIZED = 0x0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba; // keccak256(abi.encodePacked("isInitialized"))

    function setInitialize() internal {
        boolStorage[INITIALIZED] = true;
    }

    function isInitialized() public view returns (bool) {
        return boolStorage[INITIALIZED];
    }
}

// File: contracts/upgradeable_contracts/InitializableBridge.sol

pragma solidity 0.4.24;


contract InitializableBridge is Initializable {
    bytes32 internal constant DEPLOYED_AT_BLOCK = 0xb120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b0; // keccak256(abi.encodePacked("deployedAtBlock"))

    function deployedAtBlock() external view returns (uint256) {
        return uintStorage[DEPLOYED_AT_BLOCK];
    }
}

// File: openzeppelin-solidity/contracts/AddressUtils.sol

pragma solidity ^0.4.24;


/**
 * Utility library of inline functions on addresses
 */
library AddressUtils {

  /**
   * Returns whether the target address is a contract
   * @dev This function will return false if invoked during the constructor of a contract,
   * as the code is not actually created until after the constructor finishes.
   * @param _addr address to check
   * @return whether the target address is a contract
   */
  function isContract(address _addr) internal view returns (bool) {
    uint256 size;
    // XXX Currently there is no better way to check if there is a contract in an address
    // than to check the size of the code at that address.
    // See https://ethereum.stackexchange.com/a/14016/36603
    // for more details about how this works.
    // TODO Check this again before the Serenity release, because all addresses will be
    // contracts then.
    // solium-disable-next-line security/no-inline-assembly
    assembly { size := extcodesize(_addr) }
    return size > 0;
  }

}

// File: contracts/upgradeable_contracts/ValidatorStorage.sol

pragma solidity 0.4.24;

contract ValidatorStorage {
    bytes32 internal constant VALIDATOR_CONTRACT = 0x5a74bb7e202fb8e4bf311841c7d64ec19df195fee77d7e7ae749b27921b6ddfe; // keccak256(abi.encodePacked("validatorContract"))
}

// File: contracts/upgradeable_contracts/Validatable.sol

pragma solidity 0.4.24;




contract Validatable is EternalStorage, ValidatorStorage {
    function validatorContract() public view returns (IBridgeValidators) {
        return IBridgeValidators(addressStorage[VALIDATOR_CONTRACT]);
    }

    modifier onlyValidator() {
        require(validatorContract().isValidator(msg.sender));
        /* solcov ignore next */
        _;
    }

    function requiredSignatures() public view returns (uint256) {
        return validatorContract().requiredSignatures();
    }

}

// File: contracts/upgradeable_contracts/Ownable.sol

pragma solidity 0.4.24;



/**
 * @title Ownable
 * @dev This contract has an owner address providing basic authorization control
 */
contract Ownable is EternalStorage {
    bytes4 internal constant UPGRADEABILITY_OWNER = 0x6fde8202; // upgradeabilityOwner()

    /**
    * @dev Event to show ownership has been transferred
    * @param previousOwner representing the address of the previous owner
    * @param newOwner representing the address of the new owner
    */
    event OwnershipTransferred(address previousOwner, address newOwner);

    /**
    * @dev Throws if called by any account other than the owner.
    */
    modifier onlyOwner() {
        require(msg.sender == owner());
        /* solcov ignore next */
        _;
    }

    /**
    * @dev Throws if called by any account other than contract itself or owner.
    */
    modifier onlyRelevantSender() {
        // proxy owner if used through proxy, address(0) otherwise
        require(
            !address(this).call(abi.encodeWithSelector(UPGRADEABILITY_OWNER)) || // covers usage without calling through storage proxy
                msg.sender == IUpgradeabilityOwnerStorage(this).upgradeabilityOwner() || // covers usage through regular proxy calls
                msg.sender == address(this) // covers calls through upgradeAndCall proxy method
        );
        /* solcov ignore next */
        _;
    }

    bytes32 internal constant OWNER = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0; // keccak256(abi.encodePacked("owner"))

    /**
    * @dev Tells the address of the owner
    * @return the address of the owner
    */
    function owner() public view returns (address) {
        return addressStorage[OWNER];
    }

    /**
    * @dev Allows the current owner to transfer control of the contract to a newOwner.
    * @param newOwner the address to transfer ownership to.
    */
    function transferOwnership(address newOwner) external onlyOwner {
        _setOwner(newOwner);
    }

    /**
    * @dev Sets a new owner address
    */
    function _setOwner(address newOwner) internal {
        require(newOwner != address(0));
        emit OwnershipTransferred(owner(), newOwner);
        addressStorage[OWNER] = newOwner;
    }
}

// File: contracts/upgradeable_contracts/Sacrifice.sol

pragma solidity 0.4.24;

contract Sacrifice {
    constructor(address _recipient) public payable {
        selfdestruct(_recipient);
    }
}

// File: contracts/libraries/Address.sol

pragma solidity 0.4.24;


/**
 * @title Address
 * @dev Helper methods for Address type.
 */
library Address {
    /**
    * @dev Try to send native tokens to the address. If it fails, it will force the transfer by creating a selfdestruct contract
    * @param _receiver address that will receive the native tokens
    * @param _value the amount of native tokens to send
    */
    function safeSendValue(address _receiver, uint256 _value) internal {
        if (!_receiver.send(_value)) {
            (new Sacrifice).value(_value)(_receiver);
        }
    }
}

// File: openzeppelin-solidity/contracts/math/SafeMath.sol

pragma solidity ^0.4.24;


/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, throws on overflow.
  */
  function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
    // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
    if (_a == 0) {
      return 0;
    }

    c = _a * _b;
    assert(c / _a == _b);
    return c;
  }

  /**
  * @dev Integer division of two numbers, truncating the quotient.
  */
  function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
    // assert(_b > 0); // Solidity automatically throws when dividing by 0
    // uint256 c = _a / _b;
    // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold
    return _a / _b;
  }

  /**
  * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
    assert(_b <= _a);
    return _a - _b;
  }

  /**
  * @dev Adds two numbers, throws on overflow.
  */
  function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
    c = _a + _b;
    assert(c >= _a);
    return c;
  }
}

// File: openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol

pragma solidity ^0.4.24;


/**
 * @title ERC20Basic
 * @dev Simpler version of ERC20 interface
 * See https://github.com/ethereum/EIPs/issues/179
 */
contract ERC20Basic {
  function totalSupply() public view returns (uint256);
  function balanceOf(address _who) public view returns (uint256);
  function transfer(address _to, uint256 _value) public returns (bool);
  event Transfer(address indexed from, address indexed to, uint256 value);
}

// File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol

pragma solidity ^0.4.24;



/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
contract ERC20 is ERC20Basic {
  function allowance(address _owner, address _spender)
    public view returns (uint256);

  function transferFrom(address _from, address _to, uint256 _value)
    public returns (bool);

  function approve(address _spender, uint256 _value) public returns (bool);
  event Approval(
    address indexed owner,
    address indexed spender,
    uint256 value
  );
}

// File: contracts/interfaces/ERC677.sol

pragma solidity 0.4.24;


contract ERC677 is ERC20 {
    event Transfer(address indexed from, address indexed to, uint256 value, bytes data);

    function transferAndCall(address, uint256, bytes) external returns (bool);

    function increaseAllowance(address spender, uint256 addedValue) public returns (bool);
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool);
}

contract LegacyERC20 {
    function transfer(address _spender, uint256 _value) public; // returns (bool);
    function transferFrom(address _owner, address _spender, uint256 _value) public; // returns (bool);
}

// File: contracts/libraries/SafeERC20.sol

pragma solidity 0.4.24;



/**
 * @title SafeERC20
 * @dev Helper methods for safe token transfers.
 * Functions perform additional checks to be sure that token transfer really happened.
 */
library SafeERC20 {
    using SafeMath for uint256;

    /**
    * @dev Same as ERC20.transfer(address,uint256) but with extra consistency checks.
    * @param _token address of the token contract
    * @param _to address of the receiver
    * @param _value amount of tokens to send
    */
    function safeTransfer(address _token, address _to, uint256 _value) internal {
        LegacyERC20(_token).transfer(_to, _value);
        assembly {
            if returndatasize {
                returndatacopy(0, 0, 32)
                if iszero(mload(0)) {
                    revert(0, 0)
                }
            }
        }
    }

    /**
    * @dev Same as ERC20.transferFrom(address,address,uint256) but with extra consistency checks.
    * @param _token address of the token contract
    * @param _from address of the sender
    * @param _value amount of tokens to send
    */
    function safeTransferFrom(address _token, address _from, uint256 _value) internal {
        LegacyERC20(_token).transferFrom(_from, address(this), _value);
        assembly {
            if returndatasize {
                returndatacopy(0, 0, 32)
                if iszero(mload(0)) {
                    revert(0, 0)
                }
            }
        }
    }
}

// File: contracts/upgradeable_contracts/Claimable.sol

pragma solidity 0.4.24;



/**
 * @title Claimable
 * @dev Implementation of the claiming utils that can be useful for withdrawing accidentally sent tokens that are not used in bridge operations.
 */
contract Claimable {
    using SafeERC20 for address;

    /**
     * Throws if a given address is equal to address(0)
     */
    modifier validAddress(address _to) {
        require(_to != address(0));
        /* solcov ignore next */
        _;
    }

    /**
     * @dev Withdraws the erc20 tokens or native coins from this contract.
     * Caller should additionally check that the claimed token is not a part of bridge operations (i.e. that token != erc20token()).
     * @param _token address of the claimed token or address(0) for native coins.
     * @param _to address of the tokens/coins receiver.
     */
    function claimValues(address _token, address _to) internal validAddress(_to) {
        if (_token == address(0)) {
            claimNativeCoins(_to);
        } else {
            claimErc20Tokens(_token, _to);
        }
    }

    /**
     * @dev Internal function for withdrawing all native coins from the contract.
     * @param _to address of the coins receiver.
     */
    function claimNativeCoins(address _to) internal {
        uint256 value = address(this).balance;
        Address.safeSendValue(_to, value);
    }

    /**
     * @dev Internal function for withdrawing all tokens of ssome particular ERC20 contract from this contract.
     * @param _token address of the claimed ERC20 token.
     * @param _to address of the tokens receiver.
     */
    function claimErc20Tokens(address _token, address _to) internal {
        ERC20Basic token = ERC20Basic(_token);
        uint256 balance = token.balanceOf(this);
        _token.safeTransfer(_to, balance);
    }
}

// File: contracts/upgradeable_contracts/VersionableBridge.sol

pragma solidity 0.4.24;

contract VersionableBridge {
    function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
        return (6, 1, 0);
    }

    /* solcov ignore next */
    function getBridgeMode() external pure returns (bytes4);
}

// File: contracts/upgradeable_contracts/DecimalShiftBridge.sol

pragma solidity 0.4.24;



contract DecimalShiftBridge is EternalStorage {
    using SafeMath for uint256;

    bytes32 internal constant DECIMAL_SHIFT = 0x1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee5; // keccak256(abi.encodePacked("decimalShift"))

    /**
    * @dev Internal function for setting the decimal shift for bridge operations.
    * Decimal shift can be positive, negative, or equal to zero.
    * It has the following meaning: N tokens in the foreign chain are equivalent to N * pow(10, shift) tokens on the home side.
    * @param _shift new value of decimal shift.
    */
    function _setDecimalShift(int256 _shift) internal {
        // since 1 wei * 10**77 > 2**255, it does not make any sense to use higher values
        require(_shift > -77 && _shift < 77);
        uintStorage[DECIMAL_SHIFT] = uint256(_shift);
    }

    /**
    * @dev Returns the value of foreign-to-home decimal shift.
    * @return decimal shift.
    */
    function decimalShift() public view returns (int256) {
        return int256(uintStorage[DECIMAL_SHIFT]);
    }

    /**
    * @dev Converts the amount of home tokens into the equivalent amount of foreign tokens.
    * @param _value amount of home tokens.
    * @return equivalent amount of foreign tokens.
    */
    function _unshiftValue(uint256 _value) internal view returns (uint256) {
        return _shiftUint(_value, -decimalShift());
    }

    /**
    * @dev Converts the amount of foreign tokens into the equivalent amount of home tokens.
    * @param _value amount of foreign tokens.
    * @return equivalent amount of home tokens.
    */
    function _shiftValue(uint256 _value) internal view returns (uint256) {
        return _shiftUint(_value, decimalShift());
    }

    /**
    * @dev Calculates _value * pow(10, _shift).
    * @param _value amount of tokens.
    * @param _shift decimal shift to apply.
    * @return shifted value.
    */
    function _shiftUint(uint256 _value, int256 _shift) private pure returns (uint256) {
        if (_shift == 0) {
            return _value;
        }
        if (_shift > 0) {
            return _value.mul(10**uint256(_shift));
        }
        return _value.div(10**uint256(-_shift));
    }
}

// File: contracts/upgradeable_contracts/BasicBridge.sol

pragma solidity 0.4.24;









contract BasicBridge is
    InitializableBridge,
    Validatable,
    Ownable,
    Upgradeable,
    Claimable,
    VersionableBridge,
    DecimalShiftBridge
{
    event GasPriceChanged(uint256 gasPrice);
    event RequiredBlockConfirmationChanged(uint256 requiredBlockConfirmations);

    bytes32 internal constant GAS_PRICE = 0x55b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b; // keccak256(abi.encodePacked("gasPrice"))
    bytes32 internal constant REQUIRED_BLOCK_CONFIRMATIONS = 0x916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d79407230071; // keccak256(abi.encodePacked("requiredBlockConfirmations"))

    /**
    * @dev Public setter for fallback gas price value. Only bridge owner can call this method.
    * @param _gasPrice new value for the gas price.
    */
    function setGasPrice(uint256 _gasPrice) external onlyOwner {
        _setGasPrice(_gasPrice);
    }

    function gasPrice() external view returns (uint256) {
        return uintStorage[GAS_PRICE];
    }

    function setRequiredBlockConfirmations(uint256 _blockConfirmations) external onlyOwner {
        _setRequiredBlockConfirmations(_blockConfirmations);
    }

    function _setRequiredBlockConfirmations(uint256 _blockConfirmations) internal {
        require(_blockConfirmations > 0);
        uintStorage[REQUIRED_BLOCK_CONFIRMATIONS] = _blockConfirmations;
        emit RequiredBlockConfirmationChanged(_blockConfirmations);
    }

    function requiredBlockConfirmations() external view returns (uint256) {
        return uintStorage[REQUIRED_BLOCK_CONFIRMATIONS];
    }

    /**
    * @dev Internal function for updating fallback gas price value.
    * @param _gasPrice new value for the gas price, zero gas price is allowed.
    */
    function _setGasPrice(uint256 _gasPrice) internal {
        uintStorage[GAS_PRICE] = _gasPrice;
        emit GasPriceChanged(_gasPrice);
    }
}

// File: contracts/upgradeable_contracts/arbitrary_message/VersionableAMB.sol

pragma solidity 0.4.24;


contract VersionableAMB is VersionableBridge {
    // message format version as a single 4-bytes number padded to 32-bytes
    // value, included into every outgoing relay request
    //
    // the message version should be updated every time when
    // - new field appears
    // - some field removed
    // - fields order is changed
    bytes32 internal constant MESSAGE_PACKING_VERSION = 0x00050000 << 224;

    /**
     * Returns currently used bridge version
     * @return (major, minor, patch) version triple
     */
    function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
        return (6, 2, 0);
    }
}

// File: contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol

pragma solidity 0.4.24;



contract BasicAMB is BasicBridge, VersionableAMB {
    bytes32 internal constant MAX_GAS_PER_TX = 0x2670ecc91ec356e32067fd27b36614132d727b84a1e03e08f412a4f2cf075974; // keccak256(abi.encodePacked("maxGasPerTx"))
    bytes32 internal constant NONCE = 0x7ab1577440dd7bedf920cb6de2f9fc6bf7ba98c78c85a3fa1f8311aac95e1759; // keccak256(abi.encodePacked("nonce"))
    bytes32 internal constant SOURCE_CHAIN_ID = 0x67d6f42a1ed69c62022f2d160ddc6f2f0acd37ad1db0c24f4702d7d3343a4add; // keccak256(abi.encodePacked("sourceChainId"))
    bytes32 internal constant SOURCE_CHAIN_ID_LENGTH = 0xe504ae1fd6471eea80f18b8532a61a9bb91fba4f5b837f80a1cfb6752350af44; // keccak256(abi.encodePacked("sourceChainIdLength"))
    bytes32 internal constant DESTINATION_CHAIN_ID = 0xbbd454018e72a3f6c02bbd785bacc49e46292744f3f6761276723823aa332320; // keccak256(abi.encodePacked("destinationChainId"))
    bytes32 internal constant DESTINATION_CHAIN_ID_LENGTH = 0xfb792ae4ad11102b93f26a51b3749c2b3667f8b561566a4806d4989692811594; // keccak256(abi.encodePacked("destinationChainIdLength"))
    bytes32 internal constant ALLOW_REENTRANT_REQUESTS = 0xffa3a5a0e192028fc343362a39c5688e5a60819a4dc5ab3ee70c25bc25b78dd6; // keccak256(abi.encodePacked("allowReentrantRequests"))

    /**
     * Initializes AMB contract
     * @param _sourceChainId chain id of a network where this contract is deployed
     * @param _destinationChainId chain id of a network where all outgoing messages are directed
     * @param _validatorContract address of the validators contract
     * @param _maxGasPerTx maximum amount of gas per one message execution
     * @param _gasPrice default gas price used by oracles for sending transactions in this network
     * @param _requiredBlockConfirmations number of block confirmations oracle will wait before processing passed messages
     * @param _owner address of new bridge owner
     */
    function initialize(
        uint256 _sourceChainId,
        uint256 _destinationChainId,
        address _validatorContract,
        uint256 _maxGasPerTx,
        uint256 _gasPrice,
        uint256 _requiredBlockConfirmations,
        address _owner
    ) external onlyRelevantSender returns (bool) {
        require(!isInitialized());
        require(AddressUtils.isContract(_validatorContract));

        _setChainIds(_sourceChainId, _destinationChainId);
        addressStorage[VALIDATOR_CONTRACT] = _validatorContract;
        uintStorage[DEPLOYED_AT_BLOCK] = block.number;
        uintStorage[MAX_GAS_PER_TX] = _maxGasPerTx;
        _setGasPrice(_gasPrice);
        _setRequiredBlockConfirmations(_requiredBlockConfirmations);
        _setOwner(_owner);
        setInitialize();

        return isInitialized();
    }

    function getBridgeMode() external pure returns (bytes4 _data) {
        return 0x2544fbb9; // bytes4(keccak256(abi.encodePacked("arbitrary-message-bridge-core")))
    }

    function maxGasPerTx() public view returns (uint256) {
        return uintStorage[MAX_GAS_PER_TX];
    }

    function setMaxGasPerTx(uint256 _maxGasPerTx) external onlyOwner {
        uintStorage[MAX_GAS_PER_TX] = _maxGasPerTx;
    }

    /**
     * Internal function for retrieving chain id for the source network
     * @return chain id for the current network
     */
    function sourceChainId() public view returns (uint256) {
        return uintStorage[SOURCE_CHAIN_ID];
    }

    /**
     * Internal function for retrieving chain id for the destination network
     * @return chain id for the destination network
     */
    function destinationChainId() public view returns (uint256) {
        return uintStorage[DESTINATION_CHAIN_ID];
    }

    /**
     * Updates chain ids of used networks
     * @param _sourceChainId chain id for current network
     * @param _destinationChainId chain id for opposite network
     */
    function setChainIds(uint256 _sourceChainId, uint256 _destinationChainId) external onlyOwner {
        _setChainIds(_sourceChainId, _destinationChainId);
    }

    /**
     * Sets the flag to allow passing new AMB requests in the opposite direction,
     * while other AMB message is being processed.
     * Only owner can call this method.
     * @param _enable true, if reentrant requests are allowed.
     */
    function setAllowReentrantRequests(bool _enable) external onlyOwner {
        boolStorage[ALLOW_REENTRANT_REQUESTS] = _enable;
    }

    /**
     * Tells if passing reentrant requests is allowed.
     * @return true, if reentrant requests are allowed.
     */
    function allowReentrantRequests() public view returns (bool) {
        return boolStorage[ALLOW_REENTRANT_REQUESTS];
    }

    /**
     * @dev Withdraws the erc20 tokens or native coins from this contract.
     * @param _token address of the claimed token or address(0) for native coins.
     * @param _to address of the tokens/coins receiver.
     */
    function claimTokens(address _token, address _to) external onlyIfUpgradeabilityOwner {
        claimValues(_token, _to);
    }

    /**
     * Internal function for retrieving current nonce value
     * @return nonce value
     */
    function _nonce() internal view returns (uint64) {
        return uint64(uintStorage[NONCE]);
    }

    /**
     * Internal function for updating nonce value
     * @param _nonce new nonce value
     */
    function _setNonce(uint64 _nonce) internal {
        uintStorage[NONCE] = uint256(_nonce);
    }

    /**
     * Internal function for updating chain ids of used networks
     * @param _sourceChainId chain id for current network
     * @param _destinationChainId chain id for opposite network
     */
    function _setChainIds(uint256 _sourceChainId, uint256 _destinationChainId) internal {
        require(_sourceChainId > 0 && _destinationChainId > 0);
        require(_sourceChainId != _destinationChainId);

        // Length fields are needed further when encoding the message.
        // Chain ids are compressed, so that leading zero bytes are not preserved.
        // In order to save some gas during calls to MessageDelivery.c,
        // lengths of chain ids are precalculated and being saved in the storage.
        uint256 sourceChainIdLength = 0;
        uint256 destinationChainIdLength = 0;
        uint256 mask = 0xff;

        for (uint256 i = 1; sourceChainIdLength == 0 || destinationChainIdLength == 0; i++) {
            if (sourceChainIdLength == 0 && _sourceChainId & mask == _sourceChainId) {
                sourceChainIdLength = i;
            }
            if (destinationChainIdLength == 0 && _destinationChainId & mask == _destinationChainId) {
                destinationChainIdLength = i;
            }
            mask = (mask << 8) | 0xff;
        }

        uintStorage[SOURCE_CHAIN_ID] = _sourceChainId;
        uintStorage[SOURCE_CHAIN_ID_LENGTH] = sourceChainIdLength;
        uintStorage[DESTINATION_CHAIN_ID] = _destinationChainId;
        uintStorage[DESTINATION_CHAIN_ID_LENGTH] = destinationChainIdLength;
    }

    /**
     * Internal function for retrieving chain id length for the source network
     * @return chain id for the current network
     */
    function _sourceChainIdLength() internal view returns (uint256) {
        return uintStorage[SOURCE_CHAIN_ID_LENGTH];
    }

    /**
     * Internal function for retrieving chain id length for the destination network
     * @return chain id for the destination network
     */
    function _destinationChainIdLength() internal view returns (uint256) {
        return uintStorage[DESTINATION_CHAIN_ID_LENGTH];
    }

    /**
     * Internal function for validating version of the received message
     * @param _messageId id of the received message
     */
    function _isMessageVersionValid(bytes32 _messageId) internal returns (bool) {
        return
            _messageId & 0xffffffff00000000000000000000000000000000000000000000000000000000 == MESSAGE_PACKING_VERSION;
    }

    /**
     * Internal function for validating destination chain id of the received message
     * @param _chainId destination chain id of the received message
     */
    function _isDestinationChainIdValid(uint256 _chainId) internal returns (bool res) {
        return _chainId == sourceChainId();
    }
}

// File: contracts/libraries/Bytes.sol

pragma solidity 0.4.24;

/**
 * @title Bytes
 * @dev Helper methods to transform bytes to other solidity types.
 */
library Bytes {
    /**
    * @dev Converts bytes array to bytes32.
    * Truncates bytes array if its size is more than 32 bytes.
    * NOTE: This function does not perform any checks on the received parameter.
    * Make sure that the _bytes argument has a correct length, not less than 32 bytes.
    * A case when _bytes has length less than 32 will lead to the undefined behaviour,
    * since assembly will read data from memory that is not related to the _bytes argument.
    * @param _bytes to be converted to bytes32 type
    * @return bytes32 type of the firsts 32 bytes array in parameter.
    */
    function bytesToBytes32(bytes _bytes) internal pure returns (bytes32 result) {
        assembly {
            result := mload(add(_bytes, 32))
        }
    }

    /**
    * @dev Truncate bytes array if its size is more than 20 bytes.
    * NOTE: Similar to the bytesToBytes32 function, make sure that _bytes is not shorter than 20 bytes.
    * @param _bytes to be converted to address type
    * @return address included in the firsts 20 bytes of the bytes array in parameter.
    */
    function bytesToAddress(bytes _bytes) internal pure returns (address addr) {
        assembly {
            addr := mload(add(_bytes, 20))
        }
    }
}

// File: contracts/upgradeable_contracts/arbitrary_message/MessageProcessor.sol

pragma solidity 0.4.24;



contract MessageProcessor is EternalStorage {
    /**
    * @dev Returns a status of the message that came from the other side.
    * @param _messageId id of the message from the other side that triggered a call.
    * @return true if call executed successfully.
    */
    function messageCallStatus(bytes32 _messageId) external view returns (bool) {
        return boolStorage[keccak256(abi.encodePacked("messageCallStatus", _messageId))];
    }

    /**
    * @dev Sets a status of the message that came from the other side.
    * @param _messageId id of the message from the other side that triggered a call.
    * @param _status execution status, true if executed successfully.
    */
    function setMessageCallStatus(bytes32 _messageId, bool _status) internal {
        boolStorage[keccak256(abi.encodePacked("messageCallStatus", _messageId))] = _status;
    }

    /**
    * @dev Returns a data hash of the failed message that came from the other side.
    * NOTE: dataHash was used previously to identify outgoing message before AMB message id was introduced.
    * It is kept for backwards compatibility with old mediators contracts.
    * @param _messageId id of the message from the other side that triggered a call.
    * @return keccak256 hash of message data.
    */
    function failedMessageDataHash(bytes32 _messageId) external view returns (bytes32) {
        return bytes32(uintStorage[keccak256(abi.encodePacked("failedMessageDataHash", _messageId))]);
    }

    /**
    * @dev Sets a data hash of the failed message that came from the other side.
    * NOTE: dataHash was used previously to identify outgoing message before AMB message id was introduced.
    * It is kept for backwards compatibility with old mediators contracts.
    * @param _messageId id of the message from the other side that triggered a call.
    * @param data of the processed message.
    */
    function setFailedMessageDataHash(bytes32 _messageId, bytes data) internal {
        uintStorage[keccak256(abi.encodePacked("failedMessageDataHash", _messageId))] = uint256(keccak256(data));
    }

    /**
    * @dev Returns a receiver address of the failed message that came from the other side.
    * @param _messageId id of the message from the other side that triggered a call.
    * @return receiver address.
    */
    function failedMessageReceiver(bytes32 _messageId) external view returns (address) {
        return addressStorage[keccak256(abi.encodePacked("failedMessageReceiver", _messageId))];
    }

    /**
    * @dev Sets a sender address of the failed message that came from the other side.
    * @param _messageId id of the message from the other side that triggered a call.
    * @param _receiver address of the receiver.
    */
    function setFailedMessageReceiver(bytes32 _messageId, address _receiver) internal {
        addressStorage[keccak256(abi.encodePacked("failedMessageReceiver", _messageId))] = _receiver;
    }

    /**
    * @dev Returns a sender address of the failed message that came from the other side.
    * @param _messageId id of the message from the other side that triggered a call.
    * @return sender address on the other side.
    */
    function failedMessageSender(bytes32 _messageId) external view returns (address) {
        return addressStorage[keccak256(abi.encodePacked("failedMessageSender", _messageId))];
    }

    /**
    * @dev Sets a sender address of the failed message that came from the other side.
    * @param _messageId id of the message from the other side that triggered a call.
    * @param _sender address of the sender on the other side.
    */
    function setFailedMessageSender(bytes32 _messageId, address _sender) internal {
        addressStorage[keccak256(abi.encodePacked("failedMessageSender", _messageId))] = _sender;
    }

    /**
    * @dev Returns an address of the sender on the other side for the currently processed message.
    * Can be used by executors for getting other side caller address.
    * @return address of the sender on the other side.
    */
    function messageSender() external view returns (address sender) {
        assembly {
            // Even though this is not the same as addressStorage[keccak256(abi.encodePacked("messageSender"))],
            // since solidity mapping introduces another level of addressing, such slot change is safe
            // for temporary variables which are cleared at the end of the call execution.
            sender := sload(0x7b58b2a669d8e0992eae9eaef641092c0f686fd31070e7236865557fa1571b5b) // keccak256(abi.encodePacked("messageSender"))
        }
    }

    /**
    * @dev Sets an address of the sender on the other side for the currently processed message.
    * @param _sender address of the sender on the other side.
    */
    function setMessageSender(address _sender) internal {
        assembly {
            // Even though this is not the same as addressStorage[keccak256(abi.encodePacked("messageSender"))],
            // since solidity mapping introduces another level of addressing, such slot change is safe
            // for temporary variables which are cleared at the end of the call execution.
            sstore(0x7b58b2a669d8e0992eae9eaef641092c0f686fd31070e7236865557fa1571b5b, _sender) // keccak256(abi.encodePacked("messageSender"))
        }
    }

    /**
    * @dev Returns an id of the currently processed message.
    * @return id of the message that originated on the other side.
    */
    function messageId() public view returns (bytes32 id) {
        assembly {
            // Even though this is not the same as uintStorage[keccak256(abi.encodePacked("messageId"))],
            // since solidity mapping introduces another level of addressing, such slot change is safe
            // for temporary variables which are cleared at the end of the call execution.
            id := sload(0xe34bb2103dc34f2c144cc216c132d6ffb55dac57575c22e089161bbe65083304) // keccak256(abi.encodePacked("messageId"))
        }
    }

    /**
    * @dev Returns an id of the currently processed message.
    * NOTE: transactionHash was used previously to identify incoming message before AMB message id was introduced.
    * It is kept for backwards compatibility with old mediators contracts, although it doesn't return txHash anymore.
    * @return id of the message that originated on the other side.
    */
    function transactionHash() external view returns (bytes32) {
        return messageId();
    }

    /**
    * @dev Sets a message id of the currently processed message.
    * @param _messageId id of the message that originated on the other side.
    */
    function setMessageId(bytes32 _messageId) internal {
        assembly {
            // Even though this is not the same as uintStorage[keccak256(abi.encodePacked("messageId"))],
            // since solidity mapping introduces another level of addressing, such slot change is safe
            // for temporary variables which are cleared at the end of the call execution.
            sstore(0xe34bb2103dc34f2c144cc216c132d6ffb55dac57575c22e089161bbe65083304, _messageId) // keccak256(abi.encodePacked("messageId"))
        }
    }

    /**
    * @dev Returns an originating chain id of the currently processed message.
    * @return source chain id of the message that originated on the other side.
    */
    function messageSourceChainId() external view returns (uint256 id) {
        assembly {
            // Even though this is not the same as uintStorage[keccak256(abi.encodePacked("messageSourceChainId"))],
            // since solidity mapping introduces another level of addressing, such slot change is safe
            // for temporary variables which are cleared at the end of the call execution.
            id := sload(0x7f0fcd9e49860f055dd0c1682d635d309ecb5e3011654c716d9eb59a7ddec7d2) // keccak256(abi.encodePacked("messageSourceChainId"))
        }
    }

    /**
    * @dev Sets an originating chain id of the currently processed message.
    * @param _sourceChainId source chain id of the message that originated on the other side.
    */
    function setMessageSourceChainId(uint256 _sourceChainId) internal {
        assembly {
            // Even though this is not the same as uintStorage[keccak256(abi.encodePacked("messageSourceChainId"))],
            // since solidity mapping introduces another level of addressing, such slot change is safe
            // for temporary variables which are cleared at the end of the call execution.
            sstore(0x7f0fcd9e49860f055dd0c1682d635d309ecb5e3011654c716d9eb59a7ddec7d2, _sourceChainId) // keccak256(abi.encodePacked("messageSourceChainId"))
        }
    }

    /**
    * @dev Processes received message. Makes a call to the message executor,
    * sets dataHash, receive, sender variables for failed messages.
    * @param _sender sender address on the other side.
    * @param _executor address of an executor.
    * @param _messageId id of the processed message.
    * @param _gasLimit gas limit for a call to executor.
    * @param _sourceChainId source chain id is of the received message.
    * @param _data calldata for a call to executor.
    */
    function processMessage(
        address _sender,
        address _executor,
        bytes32 _messageId,
        uint256 _gasLimit,
        uint8, /* dataType */
        uint256 _sourceChainId,
        bytes memory _data
    ) internal {
        bool status = _passMessage(_sender, _executor, _data, _gasLimit, _messageId, _sourceChainId);

        setMessageCallStatus(_messageId, status);
        if (!status) {
            setFailedMessageDataHash(_messageId, _data);
            setFailedMessageReceiver(_messageId, _executor);
            setFailedMessageSender(_messageId, _sender);
        }
        emitEventOnMessageProcessed(_sender, _executor, _messageId, status);
    }

    /**
    * @dev Makes a call to the message executor.
    * @param _sender sender address on the other side.
    * @param _contract address of an executor contract.
    * @param _data calldata for a call to executor.
    * @param _gas gas limit for a call to executor. 2^32 - 1, if caller will pass all available gas for the execution.
    * @param _messageId id of the processed message.
    * @param _sourceChainId source chain id is of the received message.
    */
    function _passMessage(
        address _sender,
        address _contract,
        bytes _data,
        uint256 _gas,
        bytes32 _messageId,
        uint256 _sourceChainId
    ) internal returns (bool) {
        setMessageSender(_sender);
        setMessageId(_messageId);
        setMessageSourceChainId(_sourceChainId);

        // After EIP-150, max gas cost allowed to be passed to the internal call is equal to the 63/64 of total gas left.
        // In reality, min(gasLimit, 63/64 * gasleft()) will be used as the call gas limit.
        // Imagine a situation, when message requires 10000000 gas to be executed successfully.
        // Also suppose, that at this point, gasleft() is equal to 10158000, so the callee will receive ~ 10158000 * 63 / 64 = 9999300 gas.
        // That amount of gas is not enough, so the call will fail. At the same time,
        // even if the callee failed the bridge contract still has ~ 158000 gas to
        // finish its execution and it will be enough. The internal call fails but
        // only because the oracle provides incorrect gas limit for the transaction
        // This check is needed here in order to force contract to pass exactly the requested amount of gas.
        // Avoiding it may lead to the unwanted message failure in some extreme cases.
        require(_gas == 0xffffffff || (gasleft() * 63) / 64 > _gas);

        bool status = _contract.call.gas(_gas)(_data);
        _validateExecutionStatus(status);
        setMessageSender(address(0));
        setMessageId(bytes32(0));
        setMessageSourceChainId(0);
        return status;
    }

    /**
    * @dev Validates message execution status. In simplest case, does nothing.
    * @param _status message execution status.
    */
    function _validateExecutionStatus(bool _status) internal {
        (_status);
    }

    /* solcov ignore next */
    function emitEventOnMessageProcessed(address sender, address executor, bytes32 messageId, bool status) internal;
}

// File: contracts/upgradeable_contracts/arbitrary_message/MessageDelivery.sol

pragma solidity 0.4.24;






contract MessageDelivery is BasicAMB, MessageProcessor {
    using SafeMath for uint256;

    uint256 internal constant SEND_TO_ORACLE_DRIVEN_LANE = 0x00;
    // after EIP2929, call to warmed contract address costs 100 instead of 2600
    uint256 internal constant MIN_GAS_PER_CALL = 100;

    /**
    * @dev Requests message relay to the opposite network
    * @param _contract executor address on the other side
    * @param _data calldata passed to the executor on the other side
    * @param _gas gas limit used on the other network for executing a message
    */
    function requireToPassMessage(address _contract, bytes memory _data, uint256 _gas) public returns (bytes32) {
        return _sendMessage(_contract, _data, _gas, SEND_TO_ORACLE_DRIVEN_LANE);
    }

    /**
    * @dev Initiates sending of an AMB message to the opposite network
    * @param _contract executor address on the other side
    * @param _data calldata passed to the executor on the other side
    * @param _gas gas limit used on the other network for executing a message
    * @param _dataType AMB message dataType to be included as a part of the header
    */
    function _sendMessage(address _contract, bytes memory _data, uint256 _gas, uint256 _dataType)
        internal
        returns (bytes32)
    {
        // it is not allowed to pass messages while other messages are processed
        // if other is not explicitly configured
        require(messageId() == bytes32(0) || allowReentrantRequests());
        require(_gas >= MIN_GAS_PER_CALL && _gas <= maxGasPerTx());

        uint256 selector;
        assembly {
            selector := and(mload(add(_data, 4)), 0xffffffff)
        }
        // In order to prevent possible unauthorized ERC20 withdrawals, the following function signatures are prohibited:
        // * transfer(address,uint256)
        // * approve(address,uint256)
        // * transferFrom(address,address,uint256)
        // * approveAndCall(address,uint256,bytes)
        // * transferAndCall(address,uint256,bytes)
        // See https://medium.com/immunefi/xdai-stake-arbitrary-call-method-bug-postmortem-f80a90ac56e3 for more details
        require(
            selector != 0xa9059cbb &&
                selector != 0x095ea7b3 &&
                selector != 0x23b872dd &&
                selector != 0x4000aea0 &&
                selector != 0xcae9ca51
        );

        (bytes32 _messageId, bytes memory header) = _packHeader(_contract, _gas, _dataType);

        bytes memory eventData = abi.encodePacked(header, _data);

        emitEventOnMessageRequest(_messageId, eventData);
        return _messageId;
    }

    /**
    * @dev Packs message header into a single bytes blob
    * @param _contract executor address on the other side
    * @param _gas gas limit used on the other network for executing a message
    * @param _dataType AMB message dataType to be included as a part of the header
    */
    function _packHeader(address _contract, uint256 _gas, uint256 _dataType)
        internal
        view
        returns (bytes32 _messageId, bytes memory header)
    {
        uint256 srcChainId = sourceChainId();
        uint256 srcChainIdLength = _sourceChainIdLength();
        uint256 dstChainId = destinationChainId();
        uint256 dstChainIdLength = _destinationChainIdLength();

        _messageId = _getNewMessageId(srcChainId);

        // 79 = 4 + 20 + 8 + 20 + 20 + 4 + 1 + 1 + 1
        header = new bytes(79 + srcChainIdLength + dstChainIdLength);

        // In order to save the gas, the header is packed in the reverse order.
        // With such approach, it is possible to store right-aligned values without any additional bit shifts.
        assembly {
            let ptr := add(header, mload(header)) // points to the last word of header
            mstore(ptr, dstChainId)
            mstore(sub(ptr, dstChainIdLength), srcChainId)

            mstore(add(header, 79), _dataType)
            mstore(add(header, 78), dstChainIdLength)
            mstore(add(header, 77), srcChainIdLength)
            mstore(add(header, 76), _gas)
            mstore(add(header, 72), _contract)
            mstore(add(header, 52), caller)
            mstore(add(header, 32), _messageId)
        }
    }

    /**
     * @dev Generates a new messageId for the passed request/message.
     * Increments the nonce accordingly.
     * @param _srcChainId source chain id of the newly created message. Should be a chain id of the current network.
     * @return unique message id to use for the new request/message.
     */
    function _getNewMessageId(uint256 _srcChainId) internal returns (bytes32) {
        uint64 nonce = _nonce();
        _setNonce(nonce + 1);

        // Bridge id is recalculated every time again and again, since it is still cheaper than using SLOAD opcode (800 gas)
        bytes32 bridgeId = keccak256(abi.encodePacked(_srcChainId, address(this))) &
            0x00000000ffffffffffffffffffffffffffffffffffffffff0000000000000000;

        return MESSAGE_PACKING_VERSION | bridgeId | bytes32(nonce);
    }

    /* solcov ignore next */
    function emitEventOnMessageRequest(bytes32 messageId, bytes encodedData) internal;
}

// File: contracts/upgradeable_contracts/arbitrary_message/BasicHomeAMB.sol

pragma solidity 0.4.24;





contract BasicHomeAMB is BasicAMB, MessageDelivery {
    event SignedForUserRequest(address indexed signer, bytes32 messageHash);
    event SignedForAffirmation(address indexed signer, bytes32 messageHash);

    event CollectedSignatures(
        address authorityResponsibleForRelay,
        bytes32 messageHash,
        uint256 NumberOfCollectedSignatures
    );

    uint256 internal constant SEND_TO_MANUAL_LANE = 0x80;

    function executeAffirmation(bytes message) external onlyValidator {
        bytes32 hashMsg = keccak256(abi.encodePacked(message));
        bytes32 hashSender = keccak256(abi.encodePacked(msg.sender, hashMsg));
        // Duplicated affirmations
        require(!affirmationsSigned(hashSender));
        setAffirmationsSigned(hashSender, true);

        uint256 signed = numAffirmationsSigned(hashMsg);
        require(!isAlreadyProcessed(signed));
        // the check above assumes that the case when the value could be overflew will not happen in the addition operation below
        signed = signed + 1;

        setNumAffirmationsSigned(hashMsg, signed);

        emit SignedForAffirmation(msg.sender, hashMsg);

        if (signed >= requiredSignatures()) {
            setNumAffirmationsSigned(hashMsg, markAsProcessed(signed));
            handleMessage(message);
        }
    }

    /**
    * @dev Requests message relay to the opposite network, message is sent to the manual lane.
    * @param _contract executor address on the other side.
    * @param _data calldata passed to the executor on the other side.
    * @param _gas gas limit used on the other network for executing a message.
    */
    function requireToConfirmMessage(address _contract, bytes memory _data, uint256 _gas) public returns (bytes32) {
        return _sendMessage(_contract, _data, _gas, SEND_TO_MANUAL_LANE);
    }

    /**
     * Parses given message, processes a call inside it
     * @param _message relayed message
     */
    function handleMessage(bytes _message) internal {
        bytes32 messageId;
        address sender;
        address executor;
        uint32 gasLimit;
        uint8 dataType;
        uint256[2] memory chainIds;
        bytes memory data;

        (messageId, sender, executor, gasLimit, dataType, chainIds, data) = ArbitraryMessage.unpackData(_message);

        require(_isMessageVersionValid(messageId));
        require(_isDestinationChainIdValid(chainIds[1]));
        processMessage(sender, executor, messageId, gasLimit, dataType, chainIds[0], data);
    }

    function submitSignature(bytes signature, bytes message) external onlyValidator {
        // ensure that `signature` is really `message` signed by `msg.sender`
        require(msg.sender == Message.recoverAddressFromSignedMessage(signature, message, true));
        bytes32 hashMsg = keccak256(abi.encodePacked(message));
        bytes32 hashSender = keccak256(abi.encodePacked(msg.sender, hashMsg));

        uint256 signed = numMessagesSigned(hashMsg);
        require(!isAlreadyProcessed(signed));
        // the check above assumes that the case when the value could be overflew
        // will not happen in the addition operation below
        signed = signed + 1;
        if (signed > 1) {
            // Duplicated signatures
            require(!messagesSigned(hashSender));
        } else {
            setMessages(hashMsg, message);
        }
        setMessagesSigned(hashSender, true);

        bytes32 signIdx = keccak256(abi.encodePacked(hashMsg, (signed.sub(1))));
        setSignatures(signIdx, signature);

        setNumMessagesSigned(hashMsg, signed);

        emit SignedForUserRequest(msg.sender, hashMsg);

        uint256 reqSigs = requiredSignatures();
        if (signed >= reqSigs) {
            setNumMessagesSigned(hashMsg, markAsProcessed(signed));
            emit CollectedSignatures(msg.sender, hashMsg, reqSigs);
        }
    }

    function isAlreadyProcessed(uint256 _number) public pure returns (bool) {
        return _number & (2**255) == 2**255;
    }

    function numMessagesSigned(bytes32 _message) public view returns (uint256) {
        return uintStorage[keccak256(abi.encodePacked("numMessagesSigned", _message))];
    }

    function signature(bytes32 _hash, uint256 _index) public view returns (bytes) {
        bytes32 signIdx = keccak256(abi.encodePacked(_hash, _index));
        return bytesStorage[keccak256(abi.encodePacked("signatures", signIdx))];
    }

    function messagesSigned(bytes32 _message) public view returns (bool) {
        return boolStorage[keccak256(abi.encodePacked("messagesSigned", _message))];
    }

    function message(bytes32 _hash) public view returns (bytes) {
        return messages(_hash);
    }

    function affirmationsSigned(bytes32 _hash) public view returns (bool) {
        return boolStorage[keccak256(abi.encodePacked("affirmationsSigned", _hash))];
    }

    function numAffirmationsSigned(bytes32 _hash) public view returns (uint256) {
        return uintStorage[keccak256(abi.encodePacked("numAffirmationsSigned", _hash))];
    }

    function setMessagesSigned(bytes32 _hash, bool _status) internal {
        boolStorage[keccak256(abi.encodePacked("messagesSigned", _hash))] = _status;
    }

    function messages(bytes32 _hash) internal view returns (bytes) {
        return bytesStorage[keccak256(abi.encodePacked("messages", _hash))];
    }

    function setSignatures(bytes32 _hash, bytes _signature) internal {
        bytesStorage[keccak256(abi.encodePacked("signatures", _hash))] = _signature;
    }

    function setMessages(bytes32 _hash, bytes _message) internal {
        bytesStorage[keccak256(abi.encodePacked("messages", _hash))] = _message;
    }

    function setNumMessagesSigned(bytes32 _message, uint256 _number) internal {
        uintStorage[keccak256(abi.encodePacked("numMessagesSigned", _message))] = _number;
    }

    function markAsProcessed(uint256 _v) internal pure returns (uint256) {
        return _v | (2**255);
    }

    function setAffirmationsSigned(bytes32 _hash, bool _status) internal {
        boolStorage[keccak256(abi.encodePacked("affirmationsSigned", _hash))] = _status;
    }

    function setNumAffirmationsSigned(bytes32 _hash, uint256 _number) internal {
        uintStorage[keccak256(abi.encodePacked("numAffirmationsSigned", _hash))] = _number;
    }
}

// File: contracts/upgradeable_contracts/arbitrary_message/AsyncInformationProcessor.sol

pragma solidity 0.4.24;



/**
 * @title AsyncInformationProcessor
 * @dev Functionality for making and processing async calls on Home side of the AMB.
 */
contract AsyncInformationProcessor is BasicHomeAMB {
    event UserRequestForInformation(
        bytes32 indexed messageId,
        bytes32 indexed requestSelector,
        address indexed sender,
        bytes data
    );
    event SignedForInformation(address indexed signer, bytes32 indexed messageId);
    event InformationRetrieved(bytes32 indexed messageId, bool status, bool callbackStatus);
    event EnabledAsyncRequestSelector(bytes32 indexed requestSelector, bool enable);

    /**
     * @dev Makes an asynchronous request to get information from the opposite network.
     * Call result will be returned later to the callee, by using the onInformationReceived(bytes) callback function.
     * @param _requestSelector selector for the async request.
     * @param _data payload for the given selector
     */
    function requireToGetInformation(bytes32 _requestSelector, bytes _data) external returns (bytes32) {
        // it is not allowed to pass messages while other messages are processed
        // if other is not explicitly configured
        require(messageId() == bytes32(0) || allowReentrantRequests());
        // only contracts are allowed to call this method, since EOA won't be able to receive a callback.
        require(AddressUtils.isContract(msg.sender));

        require(isAsyncRequestSelectorEnabled(_requestSelector));

        bytes32 _messageId = _getNewMessageId(sourceChainId());

        _setAsyncRequestSender(_messageId, msg.sender);

        emit UserRequestForInformation(_messageId, _requestSelector, msg.sender, _data);
        return _messageId;
    }

    /**
     * Tells if the specific async request selector is allowed to be used and supported by the bridge oracles.
     * @param _requestSelector selector for the async request.
     * @return true, if selector is allowed to be used.
     */
    function isAsyncRequestSelectorEnabled(bytes32 _requestSelector) public view returns (bool) {
        return boolStorage[keccak256(abi.encodePacked("enableRequestSelector", _requestSelector))];
    }

    /**
     * Enables or disables the specific async request selector.
     * Only owner can call this method.
     * @param _requestSelector selector for the async request.
     * @param _enable true, if the selector should be allowed.
     */
    function enableAsyncRequestSelector(bytes32 _requestSelector, bool _enable) external onlyOwner {
        boolStorage[keccak256(abi.encodePacked("enableRequestSelector", _requestSelector))] = _enable;

        emit EnabledAsyncRequestSelector(_requestSelector, _enable);
    }

    /**
     * @dev Submits result of the async call.
     * Only validators are allowed to call this method.
     * Once enough confirmations are collected, callback function is called.
     * @param _messageId unique id of the request that was previously made.
     * @param _status true, if JSON-RPC request succeeded, false otherwise.
     * @param _result call result returned by the other side of the bridge.
     */
    function confirmInformation(bytes32 _messageId, bool _status, bytes _result) external onlyValidator {
        bytes32 hashMsg = keccak256(abi.encodePacked(_messageId, _status, _result));
        bytes32 hashSender = keccak256(abi.encodePacked(msg.sender, hashMsg));
        // Duplicated confirmations
        require(!affirmationsSigned(hashSender));
        setAffirmationsSigned(hashSender, true);

        uint256 signed = numAffirmationsSigned(hashMsg);
        require(!isAlreadyProcessed(signed));
        // the check above assumes that the case when the value could be overflew will not happen in the addition operation below
        signed = signed + 1;

        setNumAffirmationsSigned(hashMsg, signed);

        emit SignedForInformation(msg.sender, _messageId);

        if (signed >= requiredSignatures()) {
            setNumAffirmationsSigned(hashMsg, markAsProcessed(signed));
            address sender = _restoreAsyncRequestSender(_messageId);
            bytes memory data = abi.encodeWithSelector(
                IAMBInformationReceiver(address(0)).onInformationReceived.selector,
                _messageId,
                _status,
                _result
            );
            uint256 gas = maxGasPerTx();
            require((gasleft() * 63) / 64 > gas);

            bool callbackStatus = sender.call.gas(gas)(data);

            emit InformationRetrieved(_messageId, _status, callbackStatus);
        }
    }

    /**
     * Internal function for saving async request sender for future use.
     * @param _messageId id of the sent async request.
     * @param _sender address of the request sender, receiver of the callback.
     */
    function _setAsyncRequestSender(bytes32 _messageId, address _sender) internal {
        addressStorage[keccak256(abi.encodePacked("asyncSender", _messageId))] = _sender;
    }

    /**
     * Internal function for restoring async request sender information.
     * @param _messageId id of the sent async request.
     * @return address of async request sender and callback receiver.
     */
    function _restoreAsyncRequestSender(bytes32 _messageId) internal returns (address) {
        bytes32 hash = keccak256(abi.encodePacked("asyncSender", _messageId));
        address sender = addressStorage[hash];

        require(sender != address(0));

        delete addressStorage[hash];
        return sender;
    }
}

// File: contracts/upgradeable_contracts/arbitrary_message/HomeAMB.sol

pragma solidity 0.4.24;


contract HomeAMB is AsyncInformationProcessor {
    event UserRequestForSignature(bytes32 indexed messageId, bytes encodedData);
    event AffirmationCompleted(
        address indexed sender,
        address indexed executor,
        bytes32 indexed messageId,
        bool status
    );

    function emitEventOnMessageRequest(bytes32 messageId, bytes encodedData) internal {
        emit UserRequestForSignature(messageId, encodedData);
    }

    function emitEventOnMessageProcessed(address sender, address executor, bytes32 messageId, bool status) internal {
        emit AffirmationCompleted(sender, executor, messageId, status);
    }

    // selector 88414e32
    function migrateTo_6_2_0() public {
        bytes32 upgradeStorage = 0x88414e324531481ad93973c16b3c225896f52a671f48e02a8d180df7c05108c1; // keccak256(abi.encodePacked('migrateTo_6_2_0()'))
        require(!boolStorage[upgradeStorage]);

        bytes32 sel = keccak256(abi.encodePacked("eth_call(address,bytes)"));
        boolStorage[keccak256(abi.encodePacked("enableRequestSelector", sel))] = true;
        emit EnabledAsyncRequestSelector(sel, true);
        
        sel = keccak256(abi.encodePacked("eth_getBalance(address)"));
        boolStorage[keccak256(abi.encodePacked("enableRequestSelector", sel))] = true;
        emit EnabledAsyncRequestSelector(sel, true);

        sel = keccak256(abi.encodePacked("eth_getBlockByNumber(uint256)"));
        boolStorage[keccak256(abi.encodePacked("enableRequestSelector", sel))] = true;
        emit EnabledAsyncRequestSelector(sel, true);

        sel = keccak256(abi.encodePacked("eth_getBlockByHash(bytes32)"));
        boolStorage[keccak256(abi.encodePacked("enableRequestSelector", sel))] = true;
        emit EnabledAsyncRequestSelector(sel, true);

        sel = keccak256(abi.encodePacked("eth_getStorageAt(address,bytes32)"));
        boolStorage[keccak256(abi.encodePacked("enableRequestSelector", sel))] = true;
        emit EnabledAsyncRequestSelector(sel, true);

        sel = keccak256(abi.encodePacked("eth_getTransactionByHash(bytes32)"));
        boolStorage[keccak256(abi.encodePacked("enableRequestSelector", sel))] = true;
        emit EnabledAsyncRequestSelector(sel, true);

        sel = keccak256(abi.encodePacked("eth_getTransactionReceipt(bytes32)"));
        boolStorage[keccak256(abi.encodePacked("enableRequestSelector", sel))] = true;
        emit EnabledAsyncRequestSelector(sel, true);

        boolStorage[upgradeStorage] = true;
    }

}

Contract ABI

[{"constant":true,"inputs":[],"name":"transactionHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_message","type":"bytes32"}],"name":"numMessagesSigned","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_messageId","type":"bytes32"},{"name":"_status","type":"bool"},{"name":"_result","type":"bytes"}],"name":"confirmInformation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"sourceChainId","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_hash","type":"bytes32"},{"name":"_index","type":"uint256"}],"name":"signature","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sourceChainId","type":"uint256"},{"name":"_destinationChainId","type":"uint256"},{"name":"_validatorContract","type":"address"},{"name":"_maxGasPerTx","type":"uint256"},{"name":"_gasPrice","type":"uint256"},{"name":"_requiredBlockConfirmations","type":"uint256"},{"name":"_owner","type":"address"}],"name":"initialize","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"requiredBlockConfirmations","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_messageId","type":"bytes32"}],"name":"failedMessageReceiver","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBridgeMode","outputs":[{"name":"_data","type":"bytes4"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"_sourceChainId","type":"uint256"},{"name":"_destinationChainId","type":"uint256"}],"name":"setChainIds","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_hash","type":"bytes32"}],"name":"message","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_messageId","type":"bytes32"}],"name":"failedMessageSender","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"allowReentrantRequests","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_requestSelector","type":"bytes32"},{"name":"_data","type":"bytes"}],"name":"requireToGetInformation","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"signature","type":"bytes"},{"name":"message","type":"bytes"}],"name":"submitSignature","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"messageId","outputs":[{"name":"id","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_to","type":"address"}],"name":"claimTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_hash","type":"bytes32"}],"name":"numAffirmationsSigned","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_hash","type":"bytes32"}],"name":"affirmationsSigned","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_maxGasPerTx","type":"uint256"}],"name":"setMaxGasPerTx","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"migrateTo_6_2_0","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"requiredSignatures","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_message","type":"bytes32"}],"name":"messagesSigned","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_contract","type":"address"},{"name":"_data","type":"bytes"},{"name":"_gas","type":"uint256"}],"name":"requireToConfirmMessage","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"validatorContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"deployedAtBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBridgeInterfacesVersion","outputs":[{"name":"major","type":"uint64"},{"name":"minor","type":"uint64"},{"name":"patch","type":"uint64"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"messageSourceChainId","outputs":[{"name":"id","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_blockConfirmations","type":"uint256"}],"name":"setRequiredBlockConfirmations","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"destinationChainId","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_gasPrice","type":"uint256"}],"name":"setGasPrice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_enable","type":"bool"}],"name":"setAllowReentrantRequests","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_requestSelector","type":"bytes32"},{"name":"_enable","type":"bool"}],"name":"enableAsyncRequestSelector","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_messageId","type":"bytes32"}],"name":"messageCallStatus","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"messageSender","outputs":[{"name":"sender","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimalShift","outputs":[{"name":"","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_contract","type":"address"},{"name":"_data","type":"bytes"},{"name":"_gas","type":"uint256"}],"name":"requireToPassMessage","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_messageId","type":"bytes32"}],"name":"failedMessageDataHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxGasPerTx","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"message","type":"bytes"}],"name":"executeAffirmation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_requestSelector","type":"bytes32"}],"name":"isAsyncRequestSelectorEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"gasPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_number","type":"uint256"}],"name":"isAlreadyProcessed","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"messageId","type":"bytes32"},{"indexed":false,"name":"encodedData","type":"bytes"}],"name":"UserRequestForSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":true,"name":"executor","type":"address"},{"indexed":true,"name":"messageId","type":"bytes32"},{"indexed":false,"name":"status","type":"bool"}],"name":"AffirmationCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"messageId","type":"bytes32"},{"indexed":true,"name":"requestSelector","type":"bytes32"},{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"data","type":"bytes"}],"name":"UserRequestForInformation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"signer","type":"address"},{"indexed":true,"name":"messageId","type":"bytes32"}],"name":"SignedForInformation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"messageId","type":"bytes32"},{"indexed":false,"name":"status","type":"bool"},{"indexed":false,"name":"callbackStatus","type":"bool"}],"name":"InformationRetrieved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"requestSelector","type":"bytes32"},{"indexed":false,"name":"enable","type":"bool"}],"name":"EnabledAsyncRequestSelector","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"signer","type":"address"},{"indexed":false,"name":"messageHash","type":"bytes32"}],"name":"SignedForUserRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"signer","type":"address"},{"indexed":false,"name":"messageHash","type":"bytes32"}],"name":"SignedForAffirmation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"authorityResponsibleForRelay","type":"address"},{"indexed":false,"name":"messageHash","type":"bytes32"},{"indexed":false,"name":"NumberOfCollectedSignatures","type":"uint256"}],"name":"CollectedSignatures","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"gasPrice","type":"uint256"}],"name":"GasPriceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"requiredBlockConfirmations","type":"uint256"}],"name":"RequiredBlockConfirmationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousOwner","type":"address"},{"indexed":false,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]

608060405234801561001057600080fd5b50614e59806100206000396000f3006080604052600436106102165763ffffffff60e060020a6000350416630ac1c313811461021b5780630cbf0601146102425780630f08d4d01461025a5780631544298e146102865780631812d9961461029b57806325fbf4ee1461032b578063392e53cd146103785780633f0a9f651461038d5780633f9a8e7e146103a2578063437764df146103d6578063467ad35a1461041d578063490a32c6146104385780634a610b04146104505780634d4cb7a214610468578063525ea9371461047d578063630cea8e146104a1578063669f618b146104cd57806369ffa08a146104e25780636ae1a976146105095780637698da24146105215780637bac29c71461053957806388414e32146105515780638d068043146105665780638da5cb5b1461057b5780638f4b4b981461059057806394643f71146105a857806399439089146106115780639a454b99146106265780639cb7595a1461063b5780639e307dff1461067c578063acf5c68914610691578063b0750611146106a9578063bf1fe420146106be578063c2231ad2146106d6578063c29b1e8a146106f0578063cb08a10c1461070d578063d67bdd2514610725578063dae5f0fd1461073a578063dc8601b31461074f578063e37c3289146107b8578063e5789d03146107d0578063e7a2c01f146107e5578063f2fde38b14610805578063fb67e77914610826578063fe173b971461083e578063ffd19e8c14610853575b600080fd5b34801561022757600080fd5b5061023061086b565b60408051918252519081900360200190f35b34801561024e57600080fd5b5061023060043561087b565b34801561026657600080fd5b50610284600480359060248035151591604435918201910135610940565b005b34801561029257600080fd5b50610230610d74565b3480156102a757600080fd5b506102b6600435602435610dc2565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102f05781810151838201526020016102d8565b50505050905090810190601f16801561031d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561033757600080fd5b50610364600435602435600160a060020a03604435811690606435906084359060a4359060c43516610f9f565b604080519115158252519081900360200190f35b34801561038457600080fd5b50610364611213565b34801561039957600080fd5b50610230611264565b3480156103ae57600080fd5b506103ba6004356112b2565b60408051600160a060020a039092168252519081900360200190f35b3480156103e257600080fd5b506103eb611381565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff199092168252519081900360200190f35b34801561042957600080fd5b506102846004356024356113a5565b34801561044457600080fd5b506102b66004356113cf565b34801561045c57600080fd5b506103ba6004356113e0565b34801561047457600080fd5b50610364611464565b34801561048957600080fd5b506102306004803590602480359081019101356114b5565b3480156104ad57600080fd5b50610284602460048035828101929082013591813591820191013561157d565b3480156104d957600080fd5b506102306119a9565b3480156104ee57600080fd5b50610284600160a060020a03600435811690602435166119ce565b34801561051557600080fd5b50610230600435611a56565b34801561052d57600080fd5b50610364600435611ad9565b34801561054557600080fd5b50610284600435611ba2565b34801561055d57600080fd5b50610284611c0b565b34801561057257600080fd5b506102306126e7565b34801561058757600080fd5b506103ba61275f565b34801561059c57600080fd5b506103646004356127b6565b3480156105b457600080fd5b5060408051602060046024803582810135601f8101859004850286018501909652858552610230958335600160a060020a0316953695604494919390910191908190840183828082843750949750509335945061283a9350505050565b34801561061d57600080fd5b506103ba612851565b34801561063257600080fd5b506102306128a8565b34801561064757600080fd5b506106506128f6565b6040805167ffffffffffffffff9485168152928416602084015292168183015290519081900360600190f35b34801561068857600080fd5b50610230612901565b34801561069d57600080fd5b50610284600435612926565b3480156106b557600080fd5b5061023061294e565b3480156106ca57600080fd5b5061028460043561299c565b3480156106e257600080fd5b5061028460043515156129c1565b3480156106fc57600080fd5b506102846004356024351515612a38565b34801561071957600080fd5b50610364600435612b38565b34801561073157600080fd5b506103ba612bbc565b34801561074657600080fd5b50610230612be1565b34801561075b57600080fd5b5060408051602060046024803582810135601f8101859004850286018501909652858552610230958335600160a060020a03169536956044949193909101919081908401838280828437509497505093359450612c2f9350505050565b3480156107c457600080fd5b50610230600435612c3e565b3480156107dc57600080fd5b50610230612cc1565b3480156107f157600080fd5b506102846004803560248101910135612d0f565b34801561081157600080fd5b50610284600160a060020a0360043516612f96565b34801561083257600080fd5b50610364600435612fbb565b34801561084a57600080fd5b5061023061302d565b34801561085f57600080fd5b5061036460043561307b565b60006108756119a9565b90505b90565b60008060008360405160200180807f6e756d4d657373616765735369676e656400000000000000000000000000000081525060110182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106108ff5780518252601f1990920191602091820191016108e0565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205495945050505050565b6000806000806060600080610953612851565b600160a060020a031663facd743b336040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b1580156109ad57600080fd5b505af11580156109c1573d6000803e3d6000fd5b505050506040513d60208110156109d757600080fd5b505115156109e457600080fd5b8a8a8a8a604051602001808560001916600019168152602001841515151560f860020a02815260010183838082843782019150509450505050506040516020818303038152906040526040518082805190602001908083835b60208310610a5c5780518252601f199092019160209182019101610a3d565b51815160209384036101000a600019018019909216911617905260408051929094018290038220336c0100000000000000000000000002838301526034808401829052855180850390910181526054909301948590528251909d509195509293508392850191508083835b60208310610ae65780518252601f199092019160209182019101610ac7565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209550610b1e86611ad9565b15610b2857600080fd5b610b338660016130a3565b610b3c87611a56565b9450610b478561307b565b15610b5157600080fd5b846001019450610b618786613175565b6040518b9033907fa8430f88dd0556970a712fd927c7d52ff7ed1256e9c8ee3aa291cd3d6eb8205f90600090a3610b966126e7565b8510610d6757610bae87610ba98761323a565b613175565b610bb78b61325f565b604051602481018d81528c15156044830152606060648301908152608483018c90529296507ff534de5b00000000000000000000000000000000000000000000000000000000928e928e928e928e9260a401848480828437820191505095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509250610c82612cc1565b91508160405a603f02811515610c9457fe5b0411610c9f57600080fd5b83600160a060020a0316828460405180828051906020019080838360005b83811015610cd5578181015183820152602001610cbd565b50505050905090810190601f168015610d025780820380516001836020036101000a031916815260200191505b5091505060006040518083038160008787f19250505090508a600019167f11c068ae71d815e1839c207016edea79bf33158bd1f50d34e79b0c5aaf52367b8b836040518083151515158152602001821515151581526020019250505060405180910390a25b5050505050505050505050565b7f67d6f42a1ed69c62022f2d160ddc6f2f0acd37ad1db0c24f4702d7d3343a4add60009081526020527ff6c66672b1a9fe5622677597b0da8fd180a2c85696efbcf7fe4b1e0f4f0f61085490565b604080516020808201859052818301849052825180830384018152606092830193849052805192936000939192909182918401908083835b60208310610e195780518252601f199092019160209182019101610dfa565b51815160209384036101000a6000190180199092169116179052604080519290940182900382207f7369676e6174757265730000000000000000000000000000000000000000000083830152602a80840182905285518085039091018152604a9093019485905282519097506003965060009550919392508291908401908083835b60208310610eba5780518252601f199092019160209182019101610e9b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019166000191681526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f915780601f10610f6657610100808354040283529160200191610f91565b820191906000526020600020905b815481529060010190602001808311610f7457829003601f168201915b505050505091505092915050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f6fde8202000000000000000000000000000000000000000000000000000000001781529151815160009330939291829190808383895b83811015611020578181015183820152602001611008565b50505050905090810190601f16801561104d5780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af191505015806110df575030600160a060020a0316636fde82026040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156110a757600080fd5b505af11580156110bb573d6000803e3d6000fd5b505050506040513d60208110156110d157600080fd5b5051600160a060020a031633145b806110e957503330145b15156110f457600080fd5b6110fc611213565b1561110657600080fd5b61110f86613366565b151561111a57600080fd5b611124888861336e565b7fab54f3fbbe62c59b7876a9bf9bd5e0c22dbae93f4d8ee0438f7ce62b198eb0e0805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03881617905560006020819052437fe66bef0282a446f9848e2903380099bb6e431483ee78778868f33b4a154c818b557f2670ecc91ec356e32067fd27b36614132d727b84a1e03e08f412a4f2cf07597490527f3d7fe2ee9790702383ef0118b516833ef2542132d3ca4ac6c77f62f1230fa6108590556111e5846134be565b6111ee83613544565b6111f7826135d7565b6111ff6136ae565b611207611213565b98975050505050505050565b7f0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba60005260046020527f078d888f9b66f3f8bfa10909e31f1e16240db73449f0500afdbbe3a70da457cc5460ff1690565b7f916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d7940723007160009081526020527fd2ea0feb732edb0ffe32efd33a6b9d24d46b16eb34a4d07ce256537b6f131e425490565b6000600260008360405160200180807f6661696c65644d6573736167655265636569766572000000000000000000000081525060150182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106113375780518252601f199092019160209182019101611318565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a031695945050505050565b7f2544fbb90000000000000000000000000000000000000000000000000000000090565b6113ad61275f565b600160a060020a031633146113c157600080fd5b6113cb828261336e565b5050565b60606113da82613705565b92915050565b6000600260008360405160200180807f6661696c65644d65737361676553656e646572000000000000000000000000008152506013018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106113375780518252601f199092019160209182019101611318565b7fffa3a5a0e192028fc343362a39c5688e5a60819a4dc5ab3ee70c25bc25b78dd660005260046020527f265a43ea29ede07170a30cb6d77d0ab5810eee752b72432f7be348bde74aa08f5460ff1690565b600080806114c16119a9565b14806114d057506114d0611464565b15156114db57600080fd5b6114e433613366565b15156114ef57600080fd5b6114f885612fbb565b151561150357600080fd5b61151361150e610d74565b61386d565b905061151f8133613970565b60408051602080825281018590523391879184917f72220b25ff596f7113b4015af206e306c4964f58f99f01d3f439dd35575f998f9189918991908190810184848082843760405192018290039550909350505050a4949350505050565b600080600080600061158d612851565b600160a060020a031663facd743b336040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b1580156115e757600080fd5b505af11580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b5051151561161e57600080fd5b61168889898080601f0160208091040260200160405190810160405280939291908181526020018383808284375050604080516020601f8f018190048102820181019092528d815294508d93508c925082915084018382808284375060019450613a5e9350505050565b600160a060020a0316331461169c57600080fd5b8686604051602001808383808284378201915050925050506040516020818303038152906040526040518082805190602001908083835b602083106116f25780518252601f1990920191602091820191016116d3565b51815160209384036101000a600019018019909216911617905260408051929094018290038220336c0100000000000000000000000002838301526034808401829052855180850390910181526054909301948590528251909b509195509293508392850191508083835b6020831061177c5780518252601f19909201916020918201910161175d565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093506117b48561087b565b92506117bf8361307b565b156117c957600080fd5b6001928301928311156117ee576117df846127b6565b156117e957600080fd5b611828565b6118288588888080601f01602080910402602001604051908101604052809392919081815260200183838082843750613b5d945050505050565b611833846001613c34565b8461184584600163ffffffff613cb716565b604080516020808201949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b602083106118995780518252601f19909201916020918201910161187a565b51815160209384036101000a600019018019909216911617905260408051929094018290038220601f8f018290048202830182019094528d82529296506118fa9450869350918d91508c908190840183828082843750613cc9945050505050565b6119048584613d4c565b60408051868152905133917fbf06885f40778f5ccfb64497d3f92ce568ddaedb7e2fb4487f72690418cf8e4c919081900360200190a26119426126e7565b905080831061199e5761195d856119588561323a565b613d4c565b604080513381526020810187905280820183905290517f415557404d88a0c0b8e3b16967cafffc511213fd9c465c16832ee17ed57d72379181900360600190a15b505050505050505050565b7fe34bb2103dc34f2c144cc216c132d6ffb55dac57575c22e089161bbe650833045490565b30600160a060020a0316636fde82026040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015611a0c57600080fd5b505af1158015611a20573d6000803e3d6000fd5b505050506040513d6020811015611a3657600080fd5b5051600160a060020a03163314611a4c57600080fd5b6113cb8282613dce565b60008060008360405160200180807f6e756d41666669726d6174696f6e735369676e656400000000000000000000008152506015018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106108ff5780518252601f1990920191602091820191016108e0565b6000600460008360405160200180807f61666669726d6174696f6e735369676e6564000000000000000000000000000081525060120182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b60208310611b5e5780518252601f199092019160209182019101611b3f565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1695945050505050565b611baa61275f565b600160a060020a03163314611bbe57600080fd5b7f2670ecc91ec356e32067fd27b36614132d727b84a1e03e08f412a4f2cf07597460009081526020527f3d7fe2ee9790702383ef0118b516833ef2542132d3ca4ac6c77f62f1230fa61055565b7f88414e324531481ad93973c16b3c225896f52a671f48e02a8d180df7c05108c1600081815260046020527f63fce7632ff109f6b78b6333f9778ef873d98dc111299bcb4fb158905446b7b85460ff1615611c6557600080fd5b60405160200180807f6574685f63616c6c28616464726573732c62797465732900000000000000000081525060170190506040516020818303038152906040526040518082805190602001908083835b60208310611cd45780518252601f199092019160209182019101611cb5565b51815160209384036101000a600019018019909216911617905260408051929094018290038220600080516020614dee833981519152838301526035808401829052855180850390910181526055909301948590528251909750600196506004955060009492935082918401908083835b60208310611d645780518252601f199092019160209182019101611d45565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528581019690965250928301600020805460ff191695151595909517909455508051600181529051849350600080516020614e0e833981519152929181900390910190a260405160200180807f6574685f67657442616c616e636528616464726573732900000000000000000081525060170190506040516020818303038152906040526040518082805190602001908083835b60208310611e405780518252601f199092019160209182019101611e21565b51815160209384036101000a600019018019909216911617905260408051929094018290038220600080516020614dee833981519152838301526035808401829052855180850390910181526055909301948590528251909750600196506004955060009492935082918401908083835b60208310611ed05780518252601f199092019160209182019101611eb1565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528581019690965250928301600020805460ff191695151595909517909455508051600181529051849350600080516020614e0e833981519152929181900390910190a260405160200180807f6574685f676574426c6f636b42794e756d6265722875696e7432353629000000815250601d0190506040516020818303038152906040526040518082805190602001908083835b60208310611fac5780518252601f199092019160209182019101611f8d565b51815160209384036101000a600019018019909216911617905260408051929094018290038220600080516020614dee833981519152838301526035808401829052855180850390910181526055909301948590528251909750600196506004955060009492935082918401908083835b6020831061203c5780518252601f19909201916020918201910161201d565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528581019690965250928301600020805460ff191695151595909517909455508051600181529051849350600080516020614e0e833981519152929181900390910190a260405160200180807f6574685f676574426c6f636b4279486173682862797465733332290000000000815250601b0190506040516020818303038152906040526040518082805190602001908083835b602083106121185780518252601f1990920191602091820191016120f9565b51815160209384036101000a600019018019909216911617905260408051929094018290038220600080516020614dee833981519152838301526035808401829052855180850390910181526055909301948590528251909750600196506004955060009492935082918401908083835b602083106121a85780518252601f199092019160209182019101612189565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528581019690965250928301600020805460ff191695151595909517909455508051600181529051849350600080516020614e0e833981519152929181900390910190a260405160200180807f6574685f67657453746f72616765417428616464726573732c6279746573333281526020017f290000000000000000000000000000000000000000000000000000000000000081525060210190506040516020818303038152906040526040518082805190602001908083835b602083106122aa5780518252601f19909201916020918201910161228b565b51815160209384036101000a600019018019909216911617905260408051929094018290038220600080516020614dee833981519152838301526035808401829052855180850390910181526055909301948590528251909750600196506004955060009492935082918401908083835b6020831061233a5780518252601f19909201916020918201910161231b565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528581019690965250928301600020805460ff191695151595909517909455508051600181529051849350600080516020614e0e833981519152929181900390910190a260405160200180807f6574685f6765745472616e73616374696f6e427948617368286279746573333281526020017f290000000000000000000000000000000000000000000000000000000000000081525060210190506040516020818303038152906040526040518082805190602001908083835b6020831061243c5780518252601f19909201916020918201910161241d565b51815160209384036101000a600019018019909216911617905260408051929094018290038220600080516020614dee833981519152838301526035808401829052855180850390910181526055909301948590528251909750600196506004955060009492935082918401908083835b602083106124cc5780518252601f1990920191602091820191016124ad565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528581019690965250928301600020805460ff191695151595909517909455508051600181529051849350600080516020614e0e833981519152929181900390910190a260405160200180807f6574685f6765745472616e73616374696f6e526563656970742862797465733381526020017f322900000000000000000000000000000000000000000000000000000000000081525060220190506040516020818303038152906040526040518082805190602001908083835b602083106125ce5780518252601f1990920191602091820191016125af565b51815160209384036101000a600019018019909216911617905260408051929094018290038220600080516020614dee833981519152838301526035808401829052855180850390910181526055909301948590528251909750600196506004955060009492935082918401908083835b6020831061265e5780518252601f19909201916020918201910161263f565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528581019690965250928301600020805460ff191695151595909517909455508051600181529051849350600080516020614e0e833981519152929181900390910190a2506000908152600460205260409020805460ff19166001179055565b60006126f1612851565b600160a060020a0316638d0680436040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561272e57600080fd5b505af1158015612742573d6000803e3d6000fd5b505050506040513d602081101561275857600080fd5b5051905090565b7f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c060005260026020527fb7802e97e87ef2842a6cce7da7ffaeaedaa2f61a6a7870b23d9d01fc9b73712e54600160a060020a031690565b6000600460008360405160200180807f6d657373616765735369676e6564000000000000000000000000000000000000815250600e01826000191660001916815260200191505060405160208183030381529060405260405180828051906020019080838360208310611b5e5780518252601f199092019160209182019101611b3f565b60006128498484846080613e0c565b949350505050565b7f5a74bb7e202fb8e4bf311841c7d64ec19df195fee77d7e7ae749b27921b6ddfe60005260026020527fab54f3fbbe62c59b7876a9bf9bd5e0c22dbae93f4d8ee0438f7ce62b198eb0e054600160a060020a031690565b7fb120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b060009081526020527fe66bef0282a446f9848e2903380099bb6e431483ee78778868f33b4a154c818b5490565b600660026000909192565b7f7f0fcd9e49860f055dd0c1682d635d309ecb5e3011654c716d9eb59a7ddec7d25490565b61292e61275f565b600160a060020a0316331461294257600080fd5b61294b81613544565b50565b7fbbd454018e72a3f6c02bbd785bacc49e46292744f3f6761276723823aa33232060009081526020527f242329173dfc316001df0a0c3d5a8f58a7ffb1a8b7d99c268303b9a741bacdf95490565b6129a461275f565b600160a060020a031633146129b857600080fd5b61294b816134be565b6129c961275f565b600160a060020a031633146129dd57600080fd5b7fffa3a5a0e192028fc343362a39c5688e5a60819a4dc5ab3ee70c25bc25b78dd660005260046020527f265a43ea29ede07170a30cb6d77d0ab5810eee752b72432f7be348bde74aa08f805460ff1916911515919091179055565b612a4061275f565b600160a060020a03163314612a5457600080fd5b8060046000846040516020018080600080516020614dee83398151915281525060150182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b60208310612ac65780518252601f199092019160209182019101612aa7565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528581019690965250928301600020805460ff19169515159590951790945550805184151581529051859350600080516020614e0e833981519152929181900390910190a25050565b6000600460008360405160200180807f6d65737361676543616c6c537461747573000000000000000000000000000000815250601101826000191660001916815260200191505060405160208183030381529060405260405180828051906020019080838360208310611b5e5780518252601f199092019160209182019101611b3f565b7f7b58b2a669d8e0992eae9eaef641092c0f686fd31070e7236865557fa1571b5b5490565b7f1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee560009081526020527fd5c78dd9468716ca9bb96be25d56436811b20aab3523a9904b12deef1cab239d5490565b60006128498484846000613e0c565b60008060008360405160200180807f6661696c65644d657373616765446174614861736800000000000000000000008152506015018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106108ff5780518252601f1990920191602091820191016108e0565b7f2670ecc91ec356e32067fd27b36614132d727b84a1e03e08f412a4f2cf07597460009081526020527f3d7fe2ee9790702383ef0118b516833ef2542132d3ca4ac6c77f62f1230fa6105490565b6000806000612d1c612851565b600160a060020a031663facd743b336040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015612d7657600080fd5b505af1158015612d8a573d6000803e3d6000fd5b505050506040513d6020811015612da057600080fd5b50511515612dad57600080fd5b8484604051602001808383808284378201915050925050506040516020818303038152906040526040518082805190602001908083835b60208310612e035780518252601f199092019160209182019101612de4565b51815160209384036101000a600019018019909216911617905260408051929094018290038220336c01000000000000000000000000028383015260348084018290528551808503909101815260549093019485905282519099509195509293508392850191508083835b60208310612e8d5780518252601f199092019160209182019101612e6e565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150612ec582611ad9565b15612ecf57600080fd5b612eda8260016130a3565b612ee383611a56565b9050612eee8161307b565b15612ef857600080fd5b600101612f058382613175565b60408051848152905133917f5df9cc3eb93d8a9a481857a3b70a8ca966e6b80b25cf0ee2cce180ec5afa80a1919081900360200190a2612f436126e7565b8110612f8f57612f5683610ba98361323a565b612f8f85858080601f01602080910402602001604051908101604052809392919081815260200183838082843750613f92945050505050565b5050505050565b612f9e61275f565b600160a060020a03163314612fb257600080fd5b61294b816135d7565b600060046000836040516020018080600080516020614dee833981519152815250601501826000191660001916815260200191505060405160208183030381529060405260405180828051906020019080838360208310611b5e5780518252601f199092019160209182019101611b3f565b7f55b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b60009081526020527ff7d5eefab3776d7f0450bd0193564bcb4f832ce313ff2836c450fc63a4b944195490565b7f80000000000000000000000000000000000000000000000000000000000000009081161490565b80600460008460405160200180807f61666669726d6174696f6e735369676e6564000000000000000000000000000081525060120182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106131275780518252601f199092019160209182019101613108565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff1916941515949094179093555050505050565b806000808460405160200180807f6e756d41666669726d6174696f6e735369676e6564000000000000000000000081525060150182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106131f85780518252601f1990920191602091820191016131d9565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020939093555050505050565b7f80000000000000000000000000000000000000000000000000000000000000001790565b60008060008360405160200180807f6173796e6353656e646572000000000000000000000000000000000000000000815250600b0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106132e35780518252601f1990920191602091820191016132c4565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600081815260029092529290205491955050600160a060020a03169250505080151561333657600080fd5b600091825260026020526040909120805473ffffffffffffffffffffffffffffffffffffffff1916905592915050565b6000903b1190565b6000806000806000861180156133845750600085115b151561338f57600080fd5b8585141561339c57600080fd5b506000925082915060ff905060015b8315806133b6575082155b156133fe57831580156133ca575085828716145b156133d3578093505b821580156133e2575084828616145b156133eb578092505b6101009190910260ff17906001016133ab565b5050600060208190527ff6c66672b1a9fe5622677597b0da8fd180a2c85696efbcf7fe4b1e0f4f0f6108949094557f2f30286a16f86ee067618e1a246990e40c07b7749418a6dd3133f9cfb7e814cc919091557f242329173dfc316001df0a0c3d5a8f58a7ffb1a8b7d99c268303b9a741bacdf9919091557ffb792ae4ad11102b93f26a51b3749c2b3667f8b561566a4806d49896928115949091527f7b62b32ff48350e85ce95b571fde6f8b1096bc44a26db769ad6d0b3a26bf1c6d55565b7f55b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b600090815260209081527ff7d5eefab3776d7f0450bd0193564bcb4f832ce313ff2836c450fc63a4b944198290556040805183815290517f52264b89e0fceafb26e79fd49ef8a366eb6297483bf4035b027f0c99a7ad512e929181900390910190a150565b6000811161355157600080fd5b7f916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d79407230071600090815260209081527fd2ea0feb732edb0ffe32efd33a6b9d24d46b16eb34a4d07ce256537b6f131e428290556040805183815290517f4fb76205cd57c896b21511d2114137d8e901b4ccd659e1a0f97d6306795264fb929181900390910190a150565b600160a060020a03811615156135ec57600080fd5b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e061361561275f565b60408051600160a060020a03928316815291841660208301528051918290030190a17f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c060005260026020527fb7802e97e87ef2842a6cce7da7ffaeaedaa2f61a6a7870b23d9d01fc9b73712e805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b7f0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba60005260046020527f078d888f9b66f3f8bfa10909e31f1e16240db73449f0500afdbbe3a70da457cc805460ff19166001179055565b6060600360008360405160200180807f6d6573736167657300000000000000000000000000000000000000000000000081525060080182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b6020831061378a5780518252601f19909201916020918201910161376b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019166000191681526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156138615780601f1061383657610100808354040283529160200191613861565b820191906000526020600020905b81548152906001019060200180831161384457829003601f168201915b50505050509050919050565b600080600061387a614011565b91506138888260010161405f565b6040805160208082018790526c0100000000000000000000000030028284015282516034818403018152605490920192839052815191929182918401908083835b602083106138e85780518252601f1990920191602091820191016138c9565b5181516000196020949094036101000a93909301928316921916919091179052604051920182900390912067ffffffffffffffff86167bffffffffffffffffffffffffffffffffffffffff00000000000000009091169081177e0500000000000000000000000000000000000000000000000000000000000017965093505050505050919050565b80600260008460405160200180807f6173796e6353656e646572000000000000000000000000000000000000000000815250600b0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106139f45780518252601f1990920191602091820191016139d5565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0395909516949094179093555050505050565b60008060008086516041141515613a7457600080fd5b505050602084015160408501516060860151601b60ff60f860020a8304161480613aa75750601c60ff60f860020a830416145b1515613ab257600080fd5b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115613adf57600080fd5b6001613aeb87876140b6565b60408051600080825260208083018085529490945260ff60f860020a870416828401526060820188905260808201879052915160a08083019493601f198301938390039091019190865af1158015613b47573d6000803e3d6000fd5b5050604051601f19015198975050505050505050565b80600360008460405160200180807f6d6573736167657300000000000000000000000000000000000000000000000081525060080182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b60208310613be15780518252601f199092019160209182019101613bc2565b51815160001960209485036101000a01908116901991909116179052604080519490920184900390932086528583019690965250929093016000208451613c2f959194509201919050614d0a565b505050565b80600460008460405160200180807f6d657373616765735369676e6564000000000000000000000000000000000000815250600e018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106131275780518252601f199092019160209182019101613108565b600082821115613cc357fe5b50900390565b80600360008460405160200180807f7369676e61747572657300000000000000000000000000000000000000000000815250600a01826000191660001916815260200191505060405160208183030381529060405260405180828051906020019080838360208310613be15780518252601f199092019160209182019101613bc2565b806000808460405160200180807f6e756d4d657373616765735369676e65640000000000000000000000000000008152506011018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106131f85780518252601f1990920191602091820191016131d9565b80600160a060020a0381161515613de457600080fd5b600160a060020a0383161515613e0257613dfd826142d0565b613c2f565b613c2f83836142dc565b6000808060608082613e1c6119a9565b1480613e2b5750613e2b611464565b1515613e3657600080fd5b60648710158015613e4e5750613e4a612cc1565b8711155b1515613e5957600080fd5b63ffffffff60048901511693508363a9059cbb14158015613e7e57508363095ea7b314155b8015613e8e5750836323b872dd14155b8015613e9e575083634000aea014155b8015613eae57508363cae9ca5114155b1515613eb957600080fd5b613ec489888861438f565b9250925081886040516020018083805190602001908083835b60208310613efc5780518252601f199092019160209182019101613edd565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310613f445780518252601f199092019160209182019101613f25565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040529050613f858382614445565b5090979650505050505050565b6000806000806000613fa2614d88565b6060613fad886144e2565b959c50939a509198509650945092509050613fc7876145c2565b1515613fd257600080fd5b6020820151613fe090614608565b1515613feb57600080fd5b61400786868963ffffffff88168787600060200201518761461a565b5050505050505050565b7f7ab1577440dd7bedf920cb6de2f9fc6bf7ba98c78c85a3fa1f8311aac95e175960009081526020527fa9b0f75b23e377b9b22d27feaca5d8a12329c0049ebce1dc695b905f3aa4cd005490565b7f7ab1577440dd7bedf920cb6de2f9fc6bf7ba98c78c85a3fa1f8311aac95e1759600090815260205267ffffffffffffffff167fa9b0f75b23e377b9b22d27feaca5d8a12329c0049ebce1dc695b905f3aa4cd0055565b60408051808201909152601a81527f19457468657265756d205369676e6564204d6573736167653a0a00000000000060208201526000906060831561425c57816141008651614667565b866040516020018084805190602001908083835b602083106141335780518252601f199092019160209182019101614114565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b6020831061417b5780518252601f19909201916020918201910161415c565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106141c35780518252601f1990920191602091820191016141a4565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b602083106142285780518252601f199092019160209182019101614209565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902092506142c8565b6040805190810160405280600381526020017f31303400000000000000000000000000000000000000000000000000000000008152509050818186604051602001808480519060200190808383602083106141335780518252601f199092019160209182019101614114565b505092915050565b30316113cb8282614772565b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290518391600091600160a060020a038416916370a0823191602480830192602092919082900301818787803b15801561434157600080fd5b505af1158015614355573d6000803e3d6000fd5b505050506040513d602081101561436b57600080fd5b50519050614389600160a060020a038516848363ffffffff6147d316565b50505050565b600060606000806000806143a1610d74565b93506143ab614868565b92506143b561294e565b91506143bf6148b6565b90506143ca8461386d565b95508083604f01016040519080825280601f01601f1916602001820160405280156143ff578160200160208202803883390190505b50945084518501828152848282035287604f87015281604e87015283604d87015288604c8701528960488701523360348701528660208701525050505050935093915050565b604080516020808252835181830152835185937f520d2afde79cbd5db58755ac9480f81bc658e5c517fcae7365a3d832590b01839386939092839283019185019080838360005b838110156144a457818101518382015260200161448c565b50505050905090810190601f1680156144d15780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050565b60008060008060006144f2614d88565b6060600080604f915060208a01519850600160a060020a0360348b015116975060548a01518060601c975063ffffffff8160401c16965080601a1a95508060181a6001808260031b1b03818501945080858e01511687528260191a91506001808360031b1b039050818501945080858e0151166020880152848d51039350505050806040519080825280601f01601f1916602001820160405280156145a1578160200160208202803883390190505b50925060248201915080826004350160208501375050919395979092949650565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1981167e0500000000000000000000000000000000000000000000000000000000000014919050565b6000614612610d74565b909114919050565b600061462a888884888a88614904565b905061463686826149fa565b80151561465b576146478683614a7d565b6146518688614b4a565b61465b8689614bcd565b61400788888884614c50565b606060008082818515156146b05760408051808201909152600181527f300000000000000000000000000000000000000000000000000000000000000060208201529450614769565b8593505b83156146cb57600190920191600a840493506146b4565b826040519080825280601f01601f1916602001820160405280156146f9578160200160208202803883390190505b5091505060001982015b851561476557815160001982019160f860020a6030600a8a06010291849190811061472a57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a86049550614703565b8194505b50505050919050565b604051600160a060020a0383169082156108fc029083906000818181858888f1935050505015156113cb5780826147a7614da3565b600160a060020a039091168152604051908190036020019082f080158015612f8f573d6000803e3d6000fd5b82600160a060020a031663a9059cbb83836040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b15801561483657600080fd5b505af115801561484a573d6000803e3d6000fd5b505050503d15613c2f5760206000803e6000511515613c2f57600080fd5b7fe504ae1fd6471eea80f18b8532a61a9bb91fba4f5b837f80a1cfb6752350af4460009081526020527f2f30286a16f86ee067618e1a246990e40c07b7749418a6dd3133f9cfb7e814cc5490565b7ffb792ae4ad11102b93f26a51b3749c2b3667f8b561566a4806d498969281159460009081526020527f7b62b32ff48350e85ce95b571fde6f8b1096bc44a26db769ad6d0b3a26bf1c6d5490565b60008061491088614c9e565b61491984614cc2565b61492283614ce6565b8463ffffffff148061494257508460405a603f0281151561493f57fe5b04115b151561494d57600080fd5b86600160a060020a0316858760405180828051906020019080838360005b8381101561498357818101518382015260200161496b565b50505050905090810190601f1680156149b05780820380516001836020036101000a031916815260200191505b5091505060006040518083038160008787f19250505090506149d18161294b565b6149db6000614c9e565b6149e56000614cc2565b6149ef6000614ce6565b979650505050505050565b80600460008460405160200180807f6d65737361676543616c6c5374617475730000000000000000000000000000008152506011018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106131275780518252601f199092019160209182019101613108565b806040518082805190602001908083835b60208310614aad5780518252601f199092019160209182019101614a8e565b51815160001960209485036101000a01908116901991909116179052604080519490920184900384207f6661696c65644d657373616765446174614861736800000000000000000000008583015260358086018a905283518087039091018152605590950192839052845190965060009550859493508291840190808383602083106131f85780518252601f1990920191602091820191016131d9565b80600260008460405160200180807f6661696c65644d657373616765526563656976657200000000000000000000008152506015018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106139f45780518252601f1990920191602091820191016139d5565b80600260008460405160200180807f6661696c65644d65737361676553656e646572000000000000000000000000008152506013018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106139f45780518252601f1990920191602091820191016139d5565b60408051821515815290518391600160a060020a0380871692908816917fe194ef610f9150a2db4110b3db5116fd623175dca3528d7ae7046a1042f84fe7919081900360200190a450505050565b7f7b58b2a669d8e0992eae9eaef641092c0f686fd31070e7236865557fa1571b5b55565b7fe34bb2103dc34f2c144cc216c132d6ffb55dac57575c22e089161bbe6508330455565b7f7f0fcd9e49860f055dd0c1682d635d309ecb5e3011654c716d9eb59a7ddec7d255565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614d4b57805160ff1916838001178555614d78565b82800160010185558215614d78579182015b82811115614d78578251825591602001919060010190614d5d565b50614d84929150614db2565b5090565b60408051808201825290600290829080388339509192915050565b604051602180614dcd83390190565b61087891905b80821115614d845760008155600101614db85600608060405260405160208060218339810160405251600160a060020a038116ff00656e61626c655265717565737453656c6563746f7200000000000000000000000c6e335700063e42c344f1ce5a16fdc748318fa807af05984827f33946d93c4ea165627a7a7230582041d5bfbfc704ffe45f0b5d520341412bb3125dc382fdd9d4806c85b104a448010029

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.