Contract Address Details

0x6189d82b22d7A24feD26A87E9A66690a431B803E

Contract Name
HomeAMBNativeToErc20
Creator
0xb7a42b–a2a5c7 at 0x1f9e3d–ba084d
Balance
0 ELA
Tokens
Fetching tokens...
Transactions
Transfers
Gas Used
Last Balance Update
29425637
Contract name:
HomeAMBNativeToErc20




Optimization enabled
true
Compiler version
v0.4.24+commit.e67f0147




Optimization runs
200
EVM Version
byzantium




Verified at
2022-05-21 18:10:29.704314Z

Contract source code

// 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/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: 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/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: contracts/upgradeable_contracts/Claimable.sol
pragma solidity 0.4.24;
contract Claimable {
bytes4 internal constant TRANSFER = 0xa9059cbb; // transfer(address,uint256)
modifier validAddress(address _to) {
require(_to != address(0));
/* solcov ignore next */
_;
}
function claimValues(address _token, address _to) internal {
if (_token == address(0)) {
claimNativeCoins(_to);
} else {
claimErc20Tokens(_token, _to);
}
}
function claimNativeCoins(address _to) internal {
uint256 value = address(this).balance;
Address.safeSendValue(_to, value);
}
function claimErc20Tokens(address _token, address _to) internal {
ERC20Basic token = ERC20Basic(_token);
uint256 balance = token.balanceOf(this);
safeTransfer(_token, _to, balance);
}
function safeTransfer(address _token, address _to, uint256 _value) internal {
bytes memory returnData;
bool returnDataResult;
bytes memory callData = abi.encodeWithSelector(TRANSFER, _to, _value);
assembly {
let result := call(gas, _token, 0x0, add(callData, 0x20), mload(callData), 0, 32)
returnData := mload(0)
returnDataResult := mload(0)
switch result
case 0 {
revert(0, 0)
}
}
// Return data is optional
if (returnData.length > 0) {
require(returnDataResult);
}
}
}
// 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 (5, 1, 0);
}
/* solcov ignore next */
function getBridgeMode() external pure returns (bytes4);
}
// 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 {
require(newOwner != address(0));
setOwner(newOwner);
}
/**
* @dev Sets a new owner address
*/
function setOwner(address newOwner) internal {
emit OwnershipTransferred(owner(), newOwner);
addressStorage[OWNER] = newOwner;
}
}
// File: contracts/interfaces/IAMB.sol
pragma solidity 0.4.24;
interface IAMB {
function messageSender() external view returns (address);
function maxGasPerTx() external view returns (uint256);
function transactionHash() external view returns (bytes32);
function messageId() external view returns (bytes32);
function messageSourceChainId() external view returns (bytes32);
function messageCallStatus(bytes32 _messageId) external view returns (bool);
function failedMessageDataHash(bytes32 _messageId) external view returns (bytes32);
function failedMessageReceiver(bytes32 _messageId) external view returns (address);
function failedMessageSender(bytes32 _messageId) external view returns (address);
function requireToPassMessage(address _contract, bytes _data, uint256 _gas) external returns (bytes32);
function sourceChainId() external view returns (uint256);
function destinationChainId() external view returns (uint256);
}
// File: contracts/interfaces/IBlocklist.sol
pragma solidity 0.4.24;
interface IBlocklist {
function isBlocked(address _account) external view returns (bool);
function blockERC20(address _token, address _account, uint256 _value, bytes32 _messageId) external;
function blockNative(address _account, bytes32 _messageId) external payable;
function checkAndBlockERC20(address _from, address _recipient,
address _token, uint256 _value, bytes32 _messageId) public returns (bool blocked);
}
// 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: 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/BasicAMBMediator.sol
pragma solidity 0.4.24;
/**
* @title BasicAMBMediator
* @dev Basic storage and methods needed by mediators to interact with AMB bridge.
*/
contract BasicAMBMediator is Ownable {
bytes32 internal constant BRIDGE_CONTRACT = 0x811bbb11e8899da471f0e69a3ed55090fc90215227fc5fb1cb0d6e962ea7b74f; // keccak256(abi.encodePacked("bridgeContract"))
bytes32 internal constant MEDIATOR_CONTRACT = 0x98aa806e31e94a687a31c65769cb99670064dd7f5a87526da075c5fb4eab9880; // keccak256(abi.encodePacked("mediatorContract"))
bytes32 internal constant REQUEST_GAS_LIMIT = 0x2dfd6c9f781bb6bbb5369c114e949b69ebb440ef3d4dd6b2836225eb1dc3a2be; // keccak256(abi.encodePacked("requestGasLimit"))
bytes32 internal constant BLOCKLIST_CONTRACT = 0x9ba5a09a13321d5fc0d3150bbf4489a02b9b881bf70e2fc6639c91e8c5ce714c; // keccak256(abi.encodePacked("blocklistContract"))
/**
* @dev Throws if caller on the other side is not an associated mediator.
*/
modifier onlyMediator {
require(msg.sender == address(bridgeContract()));
require(messageSender() == mediatorContractOnOtherSide());
_;
}
/**
* @dev Sets the AMB bridge contract address. Only the owner can call this method.
* @param _bridgeContract the address of the bridge contract.
*/
function setBridgeContract(address _bridgeContract) external onlyOwner {
_setBridgeContract(_bridgeContract);
}
function setBlocklistContract(address _blocklistContract) external onlyOwner {
_setBlocklistContract(_blocklistContract);
}
/**
* @dev Sets the mediator contract address from the other network. Only the owner can call this method.
* @param _mediatorContract the address of the mediator contract.
*/
function setMediatorContractOnOtherSide(address _mediatorContract) external onlyOwner {
_setMediatorContractOnOtherSide(_mediatorContract);
}
/**
* @dev Sets the gas limit to be used in the message execution by the AMB bridge on the other network.
* This value can't exceed the parameter maxGasPerTx defined on the AMB bridge.
* Only the owner can call this method.
* @param _requestGasLimit the gas limit for the message execution.
*/
function setRequestGasLimit(uint256 _requestGasLimit) external onlyOwner {
_setRequestGasLimit(_requestGasLimit);
}
/**
* @dev Get the AMB interface for the bridge contract address
* @return AMB interface for the bridge contract address
*/
function bridgeContract() public view returns (IAMB) {
return IAMB(addressStorage[BRIDGE_CONTRACT]);
}
function blocklistContract() public view returns (IBlocklist) {
return IBlocklist(addressStorage[BLOCKLIST_CONTRACT]);
}
/**
* @dev Tells the mediator contract address from the other network.
* @return the address of the mediator contract.
*/
function mediatorContractOnOtherSide() public view returns (address) {
return addressStorage[MEDIATOR_CONTRACT];
}
/**
* @dev Tells the gas limit to be used in the message execution by the AMB bridge on the other network.
* @return the gas limit for the message execution.
*/
function requestGasLimit() public view returns (uint256) {
return uintStorage[REQUEST_GAS_LIMIT];
}
/**
* @dev Stores a valid AMB bridge contract address.
* @param _bridgeContract the address of the bridge contract.
*/
function _setBridgeContract(address _bridgeContract) internal {
require(AddressUtils.isContract(_bridgeContract));
addressStorage[BRIDGE_CONTRACT] = _bridgeContract;
}
/**
* @dev Stores the mediator contract address from the other network.
* @param _mediatorContract the address of the mediator contract.
*/
function _setMediatorContractOnOtherSide(address _mediatorContract) internal {
addressStorage[MEDIATOR_CONTRACT] = _mediatorContract;
}
/**
* @dev Stores the gas limit to be used in the message execution by the AMB bridge on the other network.
* @param _requestGasLimit the gas limit for the message execution.
*/
function _setRequestGasLimit(uint256 _requestGasLimit) internal {
require(_requestGasLimit <= maxGasPerTx());
uintStorage[REQUEST_GAS_LIMIT] = _requestGasLimit;
}
function _setBlocklistContract(address _blocklistContract) internal {
require(AddressUtils.isContract(_blocklistContract));
addressStorage[BLOCKLIST_CONTRACT] = _blocklistContract;
}
/**
* @dev Tells the address that generated the message on the other network that is currently being executed by
* the AMB bridge.
* @return the address of the message sender.
*/
function messageSender() internal view returns (address) {
return bridgeContract().messageSender();
}
/**
* @dev Tells the id of the message originated on the other network.
* @return the id of the message originated on the other network.
*/
function messageId() internal view returns (bytes32) {
return bridgeContract().messageId();
}
/**
* @dev Tells the maximum gas limit that a message can use on its execution by the AMB bridge on the other network.
* @return the maximum gas limit value.
*/
function maxGasPerTx() internal view returns (uint256) {
return bridgeContract().maxGasPerTx();
}
}
// 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: 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/BasicTokenBridge.sol
pragma solidity 0.4.24;
contract BasicTokenBridge is EternalStorage, Ownable, DecimalShiftBridge {
using SafeMath for uint256;
event DailyLimitChanged(uint256 newLimit);
event ExecutionDailyLimitChanged(uint256 newLimit);
bytes32 internal constant MIN_PER_TX = 0xbbb088c505d18e049d114c7c91f11724e69c55ad6c5397e2b929e68b41fa05d1; // keccak256(abi.encodePacked("minPerTx"))
bytes32 internal constant MAX_PER_TX = 0x0f8803acad17c63ee38bf2de71e1888bc7a079a6f73658e274b08018bea4e29c; // keccak256(abi.encodePacked("maxPerTx"))
bytes32 internal constant DAILY_LIMIT = 0x4a6a899679f26b73530d8cf1001e83b6f7702e04b6fdb98f3c62dc7e47e041a5; // keccak256(abi.encodePacked("dailyLimit"))
bytes32 internal constant EXECUTION_MAX_PER_TX = 0xc0ed44c192c86d1cc1ba51340b032c2766b4a2b0041031de13c46dd7104888d5; // keccak256(abi.encodePacked("executionMaxPerTx"))
bytes32 internal constant EXECUTION_DAILY_LIMIT = 0x21dbcab260e413c20dc13c28b7db95e2b423d1135f42bb8b7d5214a92270d237; // keccak256(abi.encodePacked("executionDailyLimit"))
function totalSpentPerDay(uint256 _day) public view returns (uint256) {
return uintStorage[keccak256(abi.encodePacked("totalSpentPerDay", _day))];
}
function totalExecutedPerDay(uint256 _day) public view returns (uint256) {
return uintStorage[keccak256(abi.encodePacked("totalExecutedPerDay", _day))];
}
function dailyLimit() public view returns (uint256) {
return uintStorage[DAILY_LIMIT];
}
function executionDailyLimit() public view returns (uint256) {
return uintStorage[EXECUTION_DAILY_LIMIT];
}
function maxPerTx() public view returns (uint256) {
return uintStorage[MAX_PER_TX];
}
function executionMaxPerTx() public view returns (uint256) {
return uintStorage[EXECUTION_MAX_PER_TX];
}
function minPerTx() public view returns (uint256) {
return uintStorage[MIN_PER_TX];
}
function withinLimit(uint256 _amount) public view returns (bool) {
uint256 nextLimit = totalSpentPerDay(getCurrentDay()).add(_amount);
return dailyLimit() >= nextLimit && _amount <= maxPerTx() && _amount >= minPerTx();
}
function withinExecutionLimit(uint256 _amount) public view returns (bool) {
uint256 nextLimit = totalExecutedPerDay(getCurrentDay()).add(_amount);
return executionDailyLimit() >= nextLimit && _amount <= executionMaxPerTx();
}
function getCurrentDay() public view returns (uint256) {
// solhint-disable-next-line not-rely-on-time
return now / 1 days;
}
function addTotalSpentPerDay(uint256 _day, uint256 _value) internal {
uintStorage[keccak256(abi.encodePacked("totalSpentPerDay", _day))] = totalSpentPerDay(_day).add(_value);
}
function addTotalExecutedPerDay(uint256 _day, uint256 _value) internal {
uintStorage[keccak256(abi.encodePacked("totalExecutedPerDay", _day))] = totalExecutedPerDay(_day).add(_value);
}
function setDailyLimit(uint256 _dailyLimit) external onlyOwner {
require(_dailyLimit > maxPerTx() || _dailyLimit == 0);
uintStorage[DAILY_LIMIT] = _dailyLimit;
emit DailyLimitChanged(_dailyLimit);
}
function setExecutionDailyLimit(uint256 _dailyLimit) external onlyOwner {
require(_dailyLimit > executionMaxPerTx() || _dailyLimit == 0);
uintStorage[EXECUTION_DAILY_LIMIT] = _dailyLimit;
emit ExecutionDailyLimitChanged(_dailyLimit);
}
function setExecutionMaxPerTx(uint256 _maxPerTx) external onlyOwner {
require(_maxPerTx < executionDailyLimit());
uintStorage[EXECUTION_MAX_PER_TX] = _maxPerTx;
}
function setMaxPerTx(uint256 _maxPerTx) external onlyOwner {
require(_maxPerTx == 0 || (_maxPerTx > minPerTx() && _maxPerTx < dailyLimit()));
uintStorage[MAX_PER_TX] = _maxPerTx;
}
function setMinPerTx(uint256 _minPerTx) external onlyOwner {
require(_minPerTx > 0 && _minPerTx < dailyLimit() && _minPerTx < maxPerTx());
uintStorage[MIN_PER_TX] = _minPerTx;
}
/**
* @dev Retrieves maximum available bridge amount per one transaction taking into account maxPerTx() and dailyLimit() parameters.
* @return minimum of maxPerTx parameter and remaining daily quota.
*/
function maxAvailablePerTx() public view returns (uint256) {
uint256 _maxPerTx = maxPerTx();
uint256 _dailyLimit = dailyLimit();
uint256 _spent = totalSpentPerDay(getCurrentDay());
uint256 _remainingOutOfDaily = _dailyLimit > _spent ? _dailyLimit - _spent : 0;
return _maxPerTx < _remainingOutOfDaily ? _maxPerTx : _remainingOutOfDaily;
}
function _setLimits(uint256[3] _limits) internal {
require(
_limits[2] > 0 && // minPerTx > 0
_limits[1] > _limits[2] && // maxPerTx > minPerTx
_limits[0] > _limits[1] // dailyLimit > maxPerTx
);
uintStorage[DAILY_LIMIT] = _limits[0];
uintStorage[MAX_PER_TX] = _limits[1];
uintStorage[MIN_PER_TX] = _limits[2];
emit DailyLimitChanged(_limits[0]);
}
function _setExecutionLimits(uint256[2] _limits) internal {
require(_limits[1] < _limits[0]); // foreignMaxPerTx < foreignDailyLimit
uintStorage[EXECUTION_DAILY_LIMIT] = _limits[0];
uintStorage[EXECUTION_MAX_PER_TX] = _limits[1];
emit ExecutionDailyLimitChanged(_limits[0]);
}
}
// File: contracts/upgradeable_contracts/TransferInfoStorage.sol
pragma solidity 0.4.24;
contract TransferInfoStorage is EternalStorage {
/**
* @dev Stores the value of a message sent to the AMB bridge.
* @param _messageId of the message sent to the bridge.
* @param _value amount of tokens bridged.
*/
function setMessageValue(bytes32 _messageId, uint256 _value) internal {
uintStorage[keccak256(abi.encodePacked("messageValue", _messageId))] = _value;
}
/**
* @dev Tells the amount of tokens of a message sent to the AMB bridge.
* @return value representing amount of tokens.
*/
function messageValue(bytes32 _messageId) internal view returns (uint256) {
return uintStorage[keccak256(abi.encodePacked("messageValue", _messageId))];
}
/**
* @dev Stores the receiver of a message sent to the AMB bridge.
* @param _messageId of the message sent to the bridge.
* @param _recipient receiver of the tokens bridged.
*/
function setMessageRecipient(bytes32 _messageId, address _recipient) internal {
addressStorage[keccak256(abi.encodePacked("messageRecipient", _messageId))] = _recipient;
}
/**
* @dev Tells the receiver of a message sent to the AMB bridge.
* @return address of the receiver.
*/
function messageRecipient(bytes32 _messageId) internal view returns (address) {
return addressStorage[keccak256(abi.encodePacked("messageRecipient", _messageId))];
}
/**
* @dev Sets that the message sent to the AMB bridge has been fixed.
* @param _messageId of the message sent to the bridge.
*/
function setMessageFixed(bytes32 _messageId) internal {
boolStorage[keccak256(abi.encodePacked("messageFixed", _messageId))] = true;
}
/**
* @dev Tells if a message sent to the AMB bridge has been fixed.
* @return bool indicating the status of the message.
*/
function messageFixed(bytes32 _messageId) public view returns (bool) {
return boolStorage[keccak256(abi.encodePacked("messageFixed", _messageId))];
}
}
// File: contracts/upgradeable_contracts/TokenBridgeMediator.sol
pragma solidity 0.4.24;
/**
* @title TokenBridgeMediator
* @dev Common mediator functionality to handle operations related to token bridge messages sent to AMB bridge.
*/
contract TokenBridgeMediator is BasicAMBMediator, BasicTokenBridge, TransferInfoStorage {
event FailedMessageFixed(bytes32 indexed messageId, address recipient, uint256 value);
event TokensBridged(address indexed recipient, uint256 value, bytes32 indexed messageId);
/**
* @dev Call AMB bridge to require the invocation of handleBridgedTokens method of the mediator on the other network.
* Store information related to the bridged tokens in case the message execution fails on the other network
* and the action needs to be fixed/rolled back.
* @param _from address of sender, if bridge operation fails, tokens will be returned to this address
* @param _receiver address of receiver on the other side, will eventually receive bridged tokens
* @param _value bridged amount of tokens
*/
function passMessage(address _from, address _receiver, uint256 _value) internal {
bytes4 methodSelector = this.handleBridgedTokens.selector;
bytes memory data = abi.encodeWithSelector(methodSelector, _receiver, _value);
bytes32 _messageId = bridgeContract().requireToPassMessage(
mediatorContractOnOtherSide(),
data,
requestGasLimit()
);
setMessageValue(_messageId, _value);
setMessageRecipient(_messageId, _from);
}
/**
* @dev Handles the bridged tokens. Checks that the value is inside the execution limits and invokes the method
* to execute the Mint or Unlock accordingly.
* @param _recipient address that will receive the tokens
* @param _value amount of tokens to be received
*/
function handleBridgedTokens(address _recipient, uint256 _value) external onlyMediator {
if (withinExecutionLimit(_value)) {
addTotalExecutedPerDay(getCurrentDay(), _value);
executeActionOnBridgedTokens(_recipient, _value);
} else {
executeActionOnBridgedTokensOutOfLimit(_recipient, _value);
}
}
/**
* @dev Method to be called when a bridged message execution failed. It will generate a new message requesting to
* fix/roll back the transferred assets on the other network.
* @param _messageId id of the message which execution failed.
*/
function requestFailedMessageFix(bytes32 _messageId) external {
require(!bridgeContract().messageCallStatus(_messageId));
require(bridgeContract().failedMessageReceiver(_messageId) == address(this));
require(bridgeContract().failedMessageSender(_messageId) == mediatorContractOnOtherSide());
bytes4 methodSelector = this.fixFailedMessage.selector;
bytes memory data = abi.encodeWithSelector(methodSelector, _messageId);
bridgeContract().requireToPassMessage(mediatorContractOnOtherSide(), data, requestGasLimit());
}
/**
* @dev Handles the request to fix transferred assets which bridged message execution failed on the other network.
* It uses the information stored by passMessage method when the assets were initially transferred
* @param _messageId id of the message which execution failed on the other network.
*/
function fixFailedMessage(bytes32 _messageId) external onlyMediator {
require(!messageFixed(_messageId));
address recipient = messageRecipient(_messageId);
uint256 value = messageValue(_messageId);
setMessageFixed(_messageId);
executeActionOnFixedTokens(recipient, value);
emit FailedMessageFixed(_messageId, recipient, value);
}
/* solcov ignore next */
function executeActionOnBridgedTokensOutOfLimit(address _recipient, uint256 _value) internal;
/* solcov ignore next */
function executeActionOnBridgedTokens(address _recipient, uint256 _value) internal;
/* solcov ignore next */
function executeActionOnFixedTokens(address _recipient, uint256 _value) internal;
}
// File: contracts/interfaces/IMediatorFeeManager.sol
pragma solidity 0.4.24;
interface IMediatorFeeManager {
function calculateFee(uint256) external view returns (uint256);
}
// File: contracts/upgradeable_contracts/RewardableMediator.sol
pragma solidity 0.4.24;
/**
* @title RewardableMediator
* @dev Common functionality to interact with mediator fee manager contract methods.
*/
contract RewardableMediator is Ownable {
event FeeDistributed(uint256 feeAmount, bytes32 indexed messageId);
bytes32 internal constant FEE_MANAGER_CONTRACT = 0x779a349c5bee7817f04c960f525ee3e2f2516078c38c68a3149787976ee837e5; // keccak256(abi.encodePacked("feeManagerContract"))
bytes4 internal constant ON_TOKEN_TRANSFER = 0xa4c0ed36; // onTokenTransfer(address,uint256,bytes)
/**
* @dev Sets the fee manager contract address. Only the owner can call this method.
* @param _feeManager the address of the fee manager contract.
*/
function setFeeManagerContract(address _feeManager) external onlyOwner {
_setFeeManagerContract(_feeManager);
}
/**
* @dev Internal function for enabling new / disabling fee manage contract.
* @param _feeManager the address of the fee manager contract.
*/
function _setFeeManagerContract(address _feeManager) internal {
require(_feeManager == address(0) || AddressUtils.isContract(_feeManager));
addressStorage[FEE_MANAGER_CONTRACT] = _feeManager;
}
/**
* @dev Tells the fee manager contract address
* @return the address of the fee manager contract.
*/
function feeManagerContract() public view returns (IMediatorFeeManager) {
return IMediatorFeeManager(addressStorage[FEE_MANAGER_CONTRACT]);
}
/**
* @dev Distributes the provided amount of fees.
* @param _feeManager address of the fee manager contract
* @param _fee total amount to be distributed to the list of reward accounts.
* @param _messageId id of the message that generated fee distribution
*/
function distributeFee(IMediatorFeeManager _feeManager, uint256 _fee, bytes32 _messageId) internal {
onFeeDistribution(_feeManager, _fee);
_feeManager.call(abi.encodeWithSelector(ON_TOKEN_TRANSFER, address(this), _fee, ""));
emit FeeDistributed(_fee, _messageId);
}
/* solcov ignore next */
function onFeeDistribution(address _feeManager, uint256 _fee) internal;
}
// File: contracts/upgradeable_contracts/amb_native_to_erc20/BasicAMBNativeToErc20.sol
pragma solidity 0.4.24;
/**
* @title BasicAMBNativeToErc20
* @dev Common mediator functionality for native-to-erc20 bridge intended to work on top of AMB bridge.
*/
contract BasicAMBNativeToErc20 is
Initializable,
Upgradeable,
Claimable,
VersionableBridge,
TokenBridgeMediator,
RewardableMediator
{
/**
* @dev Stores the initial parameters of the mediator.
* @param _bridgeContract the address of the AMB bridge contract.
* @param _mediatorContract the address of the mediator contract on the other network.
* @param _dailyLimitMaxPerTxMinPerTxArray array with limit values for the assets to be bridged to the other network.
* [ 0 = dailyLimit, 1 = maxPerTx, 2 = minPerTx ]
* @param _executionDailyLimitExecutionMaxPerTxArray array with limit values for the assets bridged from the other network.
* [ 0 = executionDailyLimit, 1 = executionMaxPerTx ]
* @param _requestGasLimit the gas limit for the message execution.
* @param _decimalShift number of decimals shift required to adjust the amount of tokens bridged.
* @param _owner address of the owner of the mediator contract
* @param _feeManager address of the fee manager contract
*/
function _initialize(
address _bridgeContract,
address _mediatorContract,
uint256[3] _dailyLimitMaxPerTxMinPerTxArray,
uint256[2] _executionDailyLimitExecutionMaxPerTxArray,
uint256 _requestGasLimit,
int256 _decimalShift,
address _owner,
address _feeManager
) internal {
require(!isInitialized());
require(_owner != address(0));
_setBridgeContract(_bridgeContract);
_setMediatorContractOnOtherSide(_mediatorContract);
_setRequestGasLimit(_requestGasLimit);
_setLimits(_dailyLimitMaxPerTxMinPerTxArray);
_setExecutionLimits(_executionDailyLimitExecutionMaxPerTxArray);
_setDecimalShift(_decimalShift);
_setFeeManagerContract(_feeManager);
setOwner(_owner);
}
/**
* @dev Tells the bridge interface version that this contract supports.
* @return major value of the version
* @return minor value of the version
* @return patch value of the version
*/
function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
return (1, 1, 0);
}
/**
* @dev Tells the bridge mode that this contract supports.
* @return _data 4 bytes representing the bridge mode
*/
function getBridgeMode() external pure returns (bytes4 _data) {
return 0x582ed8fd; // bytes4(keccak256(abi.encodePacked("native-to-erc-amb")))
}
/**
* @dev Execute the action to be performed when the bridge tokens are out of execution limits.
*/
function executeActionOnBridgedTokensOutOfLimit(
address, /* _recipient */
uint256 /* _value */
) internal {
revert();
}
/**
* @dev Allows to transfer any locked token on this contract that is not part of the bridge operations.
* @param _token address of the token, if it is not provided, native tokens will be transferred.
* @param _to address that will receive the locked tokens on this contract.
*/
function claimTokens(address _token, address _to) public onlyIfUpgradeabilityOwner validAddress(_to) {
claimValues(_token, _to);
}
}
// File: contracts/upgradeable_contracts/amb_native_to_erc20/HomeAMBNativeToErc20.sol
pragma solidity 0.4.24;
/**
* @title HomeAMBNativeToErc20
* @dev Home mediator implementation for native-to-erc20 bridge intended to work on top of AMB bridge.
* It is design to be used as implementation contract of EternalStorageProxy contract.
*/
contract HomeAMBNativeToErc20 is BasicAMBNativeToErc20 {
bytes32 internal constant MEDIATOR_BALANCE = 0x3db340e280667ee926fa8c51e8f9fcf88a0ff221a66d84d63b4778127d97d139; // keccak256(abi.encodePacked("mediatorBalance"))
/**
* @dev Stores the initial parameters of the mediator.
* @param _bridgeContract the address of the AMB bridge contract.
* @param _mediatorContract the address of the mediator contract on the other network.
* @param _dailyLimitMaxPerTxMinPerTxArray array with limit values for the assets to be bridged to the other network.
* [ 0 = dailyLimit, 1 = maxPerTx, 2 = minPerTx ]
* @param _executionDailyLimitExecutionMaxPerTxArray array with limit values for the assets bridged from the other network.
* [ 0 = executionDailyLimit, 1 = executionMaxPerTx ]
* @param _requestGasLimit the gas limit for the message execution.
* @param _decimalShift number of decimals shift required to adjust the amount of tokens bridged.
* @param _owner address of the owner of the mediator contract
* @param _feeManager address of the fee manager contract
*/
function initialize(
address _bridgeContract,
address _mediatorContract,
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = dailyLimit, 1 = maxPerTx, 2 = minPerTx ]
uint256[2] _executionDailyLimitExecutionMaxPerTxArray, // [ 0 = executionDailyLimit, 1 = executionMaxPerTx ]
uint256 _requestGasLimit,
int256 _decimalShift,
address _owner,
address _feeManager
) external onlyRelevantSender returns (bool) {
_initialize(
_bridgeContract,
_mediatorContract,
_dailyLimitMaxPerTxMinPerTxArray,
_executionDailyLimitExecutionMaxPerTxArray,
_requestGasLimit,
_decimalShift,
_owner,
_feeManager
);
setInitialize();
return isInitialized();
}
/**
* @dev Fallback method to be called to initiate the bridge operation of the native tokens to an erc20 representation
* that the user will receive in the same address on the other network.
*/
function() public payable {
require(msg.data.length == 0);
nativeTransfer(msg.sender);
}
/**
* @dev Method to be called to initiate the bridge operation of the native tokens to an erc20 representation
* that the user will receive in the address specified by parameter on the other network.
* @param _receiver address that will receive the erc20 tokens on the other network.
*/
function relayTokens(address _receiver) external payable {
nativeTransfer(_receiver);
}
/**
* @dev Validates the received native tokens and makes the request to mint the erc20 tokens on the other network.
* @param _receiver address that will receive the erc20 tokens on the other network.
*/
function nativeTransfer(address _receiver) internal {
require(msg.value > 0);
require(withinLimit(msg.value));
// check sender and receiver is blocked
IBlocklist blocklist = blocklistContract();
if (blocklist != address(0) && blocklist.isBlocked(msg.sender)) {
blocklist.blockNative.value(msg.value)(msg.sender, 0);
return;
}
if (blocklist != address(0) && blocklist.isBlocked(_receiver)) {
blocklist.blockNative.value(msg.value)(_receiver, 0);
return;
}
addTotalSpentPerDay(getCurrentDay(), msg.value);
setMediatorBalance(mediatorBalance().add(msg.value));
passMessage(msg.sender, _receiver, msg.value);
}
/**
* @dev Transfers the amount of locked native tokens that were bridged from the other network.
* If configured, it calculates, subtract and distribute the fees among the reward accounts.
* @param _receiver address that will receive the native tokens
* @param _value amount of native tokens to be received
*/
function executeActionOnBridgedTokens(address _receiver, uint256 _value) internal {
uint256 valueToTransfer = _shiftValue(_value);
setMediatorBalance(mediatorBalance().sub(valueToTransfer));
bytes32 _messageId = messageId();
// check receiver is blocked
IBlocklist blocklist = blocklistContract();
if (blocklist != address(0) && blocklist.isBlocked(_receiver)) {
blocklist.blockNative.value(valueToTransfer)(_receiver, _messageId);
return;
}
IMediatorFeeManager feeManager = feeManagerContract();
if (feeManager != address(0)) {
uint256 fee = feeManager.calculateFee(valueToTransfer);
if (fee != 0) {
distributeFee(feeManager, fee, _messageId);
valueToTransfer = valueToTransfer.sub(fee);
}
}
Address.safeSendValue(_receiver, valueToTransfer);
emit TokensBridged(_receiver, valueToTransfer, _messageId);
}
/**
* @dev Transfers back the amount of locked native tokens that were bridged to the other network but failed.
* @param _receiver address that will receive the native tokens
* @param _value amount of native tokens to be received
*/
function executeActionOnFixedTokens(address _receiver, uint256 _value) internal {
setMediatorBalance(mediatorBalance().sub(_value));
// check receiver is blocked
IBlocklist blocklist = blocklistContract();
if (blocklist != address(0) && blocklist.isBlocked(_receiver)) {
blocklist.blockNative.value(_value)(_receiver, messageId());
return;
}
Address.safeSendValue(_receiver, _value);
}
/**
* @dev Transfer the fee amount as native tokens to the fee manager contract.
* @param _feeManager address that will receive the native tokens.
* @param _fee amount of native tokens to be distribute.
*/
function onFeeDistribution(address _feeManager, uint256 _fee) internal {
Address.safeSendValue(_feeManager, _fee);
}
/**
* @dev Tells the native balance of the contract.
* @return the current tracked native balance of the contract.
*/
function mediatorBalance() public view returns (uint256) {
return uintStorage[MEDIATOR_BALANCE];
}
/**
* @dev Sets the updated native balance of the contract.
* @param _balance the new native balance of the contract.
*/
function setMediatorBalance(uint256 _balance) internal {
uintStorage[MEDIATOR_BALANCE] = _balance;
}
/**
* @dev Allows to transfer any locked token on this contract that is not part of the bridge operations.
* Native tokens are not allowed to be claimed.
* @param _token address of the token.
* @param _to address that will receive the locked tokens on this contract.
*/
function claimTokens(address _token, address _to) public {
require(_token != address(0));
super.claimTokens(_token, _to);
}
/**
* @dev Allows to send to the other network the amount of locked native tokens that can be forced into the contract
* without the invocation of the required methods.
* @param _receiver the address that will receive the tokens on the other network
*/
function fixMediatorBalance(address _receiver) public onlyIfUpgradeabilityOwner {
uint256 balance = address(this).balance;
uint256 expectedBalance = mediatorBalance();
require(balance > expectedBalance);
uint256 diff = balance - expectedBalance;
uint256 available = maxAvailablePerTx();
require(available > 0);
if (diff > available) {
diff = available;
}
addTotalSpentPerDay(getCurrentDay(), diff);
setMediatorBalance(expectedBalance.add(diff));
passMessage(_receiver, _receiver, diff);
}
}

Contract ABI

[{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"fixFailedMessage","inputs":[{"type":"bytes32","name":"_messageId"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setBridgeContract","inputs":[{"type":"address","name":"_bridgeContract"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"blocklistContract","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"totalSpentPerDay","inputs":[{"type":"uint256","name":"_day"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isInitialized","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setExecutionDailyLimit","inputs":[{"type":"uint256","name":"_dailyLimit"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getCurrentDay","inputs":[],"constant":true},{"type":"function","stateMutability":"pure","payable":false,"outputs":[{"type":"bytes4","name":"_data"}],"name":"getBridgeMode","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"executionDailyLimit","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"mediatorBalance","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"totalExecutedPerDay","inputs":[{"type":"uint256","name":"_day"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"initialize","inputs":[{"type":"address","name":"_bridgeContract"},{"type":"address","name":"_mediatorContract"},{"type":"uint256[3]","name":"_dailyLimitMaxPerTxMinPerTxArray"},{"type":"uint256[2]","name":"_executionDailyLimitExecutionMaxPerTxArray"},{"type":"uint256","name":"_requestGasLimit"},{"type":"int256","name":"_decimalShift"},{"type":"address","name":"_owner"},{"type":"address","name":"_feeManager"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"fixMediatorBalance","inputs":[{"type":"address","name":"_receiver"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"messageFixed","inputs":[{"type":"bytes32","name":"_messageId"}],"constant":true},{"type":"function","stateMutability":"payable","payable":true,"outputs":[],"name":"relayTokens","inputs":[{"type":"address","name":"_receiver"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setFeeManagerContract","inputs":[{"type":"address","name":"_feeManager"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"dailyLimit","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"claimTokens","inputs":[{"type":"address","name":"_token"},{"type":"address","name":"_to"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setMediatorContractOnOtherSide","inputs":[{"type":"address","name":"_mediatorContract"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"mediatorContractOnOtherSide","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"withinExecutionLimit","inputs":[{"type":"uint256","name":"_amount"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"executionMaxPerTx","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"handleBridgedTokens","inputs":[{"type":"address","name":"_recipient"},{"type":"uint256","name":"_value"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"owner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"maxAvailablePerTx","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"requestFailedMessageFix","inputs":[{"type":"bytes32","name":"_messageId"}],"constant":false},{"type":"function","stateMutability":"pure","payable":false,"outputs":[{"type":"uint64","name":"major"},{"type":"uint64","name":"minor"},{"type":"uint64","name":"patch"}],"name":"getBridgeInterfacesVersion","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setMinPerTx","inputs":[{"type":"uint256","name":"_minPerTx"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setBlocklistContract","inputs":[{"type":"address","name":"_blocklistContract"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setDailyLimit","inputs":[{"type":"uint256","name":"_dailyLimit"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"requestGasLimit","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setMaxPerTx","inputs":[{"type":"uint256","name":"_maxPerTx"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"bridgeContract","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"int256","name":""}],"name":"decimalShift","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"feeManagerContract","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"minPerTx","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"withinLimit","inputs":[{"type":"uint256","name":"_amount"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setExecutionMaxPerTx","inputs":[{"type":"uint256","name":"_maxPerTx"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setRequestGasLimit","inputs":[{"type":"uint256","name":"_requestGasLimit"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"maxPerTx","inputs":[],"constant":true},{"type":"fallback","stateMutability":"payable","payable":true},{"type":"event","name":"FeeDistributed","inputs":[{"type":"uint256","name":"feeAmount","indexed":false},{"type":"bytes32","name":"messageId","indexed":true}],"anonymous":false},{"type":"event","name":"FailedMessageFixed","inputs":[{"type":"bytes32","name":"messageId","indexed":true},{"type":"address","name":"recipient","indexed":false},{"type":"uint256","name":"value","indexed":false}],"anonymous":false},{"type":"event","name":"TokensBridged","inputs":[{"type":"address","name":"recipient","indexed":true},{"type":"uint256","name":"value","indexed":false},{"type":"bytes32","name":"messageId","indexed":true}],"anonymous":false},{"type":"event","name":"DailyLimitChanged","inputs":[{"type":"uint256","name":"newLimit","indexed":false}],"anonymous":false},{"type":"event","name":"ExecutionDailyLimitChanged","inputs":[{"type":"uint256","name":"newLimit","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","indexed":false},{"type":"address","name":"newOwner","indexed":false}],"anonymous":false}]
            

Deployed ByteCode

0x6080604052600436106101df5763ffffffff60e060020a6000350416630950d51581146101f55780630b26cf661461020d578063151a62081461022e5780632bd0bb051461025f578063392e53cd146102895780633dd95d1b146102b25780633e6968b6146102ca578063437764df146102df57806343b37dd3146103295780634b94f8151461033e5780634fb3fef714610353578063521c5dcf1461036b57806358bf7c79146103af57806359339982146103d05780635d1e9307146103e857806360756f7c146103fc57806367eeba0c1461041d57806369ffa08a146104325780636e5d6bea14610459578063871c07601461047a578063879ce6761461048f5780638aa1949a146104a75780638b6c0354146104bc5780638da5cb5b146104e057806395e54a17146104f55780639a4a43951461050a5780639cb7595a14610522578063a2a6ca2714610563578063a3f386051461057b578063b20d30a91461059c578063be3b625b146105b4578063c6f6f216146105c9578063cd596583146105e1578063dae5f0fd146105f6578063dbe03a8b1461060b578063df25f3f014610620578063ea9f496814610635578063f20151e11461064d578063f2fde38b14610665578063f3b8379114610686578063f968adbe1461069e575b36156101ea57600080fd5b6101f3336106b3565b005b34801561020157600080fd5b506101f3600435610954565b34801561021957600080fd5b506101f3600160a060020a0360043516610a23565b34801561023a57600080fd5b50610243610a4b565b60408051600160a060020a039092168252519081900360200190f35b34801561026b57600080fd5b50610277600435610aa2565b60408051918252519081900360200190f35b34801561029557600080fd5b5061029e610b5f565b604080519115158252519081900360200190f35b3480156102be57600080fd5b506101f3600435610bb0565b3480156102d657600080fd5b50610277610c70565b3480156102eb57600080fd5b506102f4610c79565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b34801561033557600080fd5b50610277610c9d565b34801561034a57600080fd5b50610277610ceb565b34801561035f57600080fd5b50610277600435610d38565b34801561037757600080fd5b5061029e600160a060020a0360043581169060243581169060449060a49060e435906101043590610124358116906101443516610db3565b3480156103bb57600080fd5b506101f3600160a060020a0360043516610f60565b3480156103dc57600080fd5b5061029e60043561105c565b6101f3600160a060020a0360043516611125565b34801561040857600080fd5b506101f3600160a060020a036004351661112e565b34801561042957600080fd5b50610277611153565b34801561043e57600080fd5b506101f3600160a060020a03600435811690602435166111a1565b34801561046557600080fd5b506101f3600160a060020a03600435166111c0565b34801561048657600080fd5b506102436111e5565b34801561049b57600080fd5b5061029e60043561123c565b3480156104b357600080fd5b5061027761127a565b3480156104c857600080fd5b506101f3600160a060020a03600435166024356112c8565b3480156104ec57600080fd5b50610243611348565b34801561050157600080fd5b5061027761139f565b34801561051657600080fd5b506101f36004356113f9565b34801561052e57600080fd5b5061053761172e565b6040805167ffffffffffffffff9485168152928416602084015292168183015290519081900360600190f35b34801561056f57600080fd5b506101f3600435611738565b34801561058757600080fd5b506101f3600160a060020a03600435166117d4565b3480156105a857600080fd5b506101f36004356117f9565b3480156105c057600080fd5b506102776118b9565b3480156105d557600080fd5b506101f3600435611907565b3480156105ed57600080fd5b5061024361199f565b34801561060257600080fd5b506102776119f6565b34801561061757600080fd5b50610243611a44565b34801561062c57600080fd5b50610277611a9b565b34801561064157600080fd5b5061029e600435611ae9565b34801561065957600080fd5b506101f3600435611b34565b34801561067157600080fd5b506101f3600160a060020a0360043516611bb0565b34801561069257600080fd5b506101f3600435611bea565b3480156106aa57600080fd5b50610277611c0f565b60003481106106c157600080fd5b6106ca34611ae9565b15156106d557600080fd5b6106dd610a4b565b9050600160a060020a038116158015906107805750604080517ffbac39510000000000000000000000000000000000000000000000000000000081523360048201529051600160a060020a0383169163fbac39519160248083019260209291908290030181600087803b15801561075357600080fd5b505af1158015610767573d6000803e3d6000fd5b505050506040513d602081101561077d57600080fd5b50515b1561080a57604080517f6cac044a0000000000000000000000000000000000000000000000000000000081523360048201526000602482018190529151600160a060020a03841692636cac044a9234926044808301939282900301818588803b1580156107ec57600080fd5b505af1158015610800573d6000803e3d6000fd5b5050505050610950565b600160a060020a038116158015906108a5575080600160a060020a031663fbac3951836040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801561087857600080fd5b505af115801561088c573d6000803e3d6000fd5b505050506040513d60208110156108a257600080fd5b50515b1561091457604080517f6cac044a000000000000000000000000000000000000000000000000000000008152600160a060020a038481166004830152600060248301819052925190841692636cac044a9234926044808301939282900301818588803b1580156107ec57600080fd5b61092561091f610c70565b34611c5d565b61094561094034610934610ceb565b9063ffffffff611d2616565b611d39565b610950338334611d85565b5050565b60008061095f61199f565b600160a060020a0316331461097357600080fd5b61097b6111e5565b600160a060020a031661098c611f17565b600160a060020a03161461099f57600080fd5b6109a88361105c565b156109b257600080fd5b6109bb83611f8f565b91506109c68361205e565b90506109d1836120e1565b6109db82826121b3565b60408051600160a060020a038416815260208101839052815185927f06297b0797e3363e96e454edd4ab62862051bf559a7a431ce09415306771d133928290030190a2505050565b610a2b611348565b600160a060020a03163314610a3f57600080fd5b610a488161230c565b50565b7f9ba5a09a13321d5fc0d3150bbf4489a02b9b881bf70e2fc6639c91e8c5ce714c60005260026020527f87f07cf898f772bd3ff661aa30d2354333eefbd852e374d9021ef7a3463e81fd54600160a060020a031690565b60008060008360405160200180807f746f74616c5370656e74506572446179000000000000000000000000000000008152506010018281526020019150506040516020818303038152906040526040518082805190602001908083835b60208310610b1e5780518252601f199092019160209182019101610aff565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205495945050505050565b7f0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba60005260046020527f078d888f9b66f3f8bfa10909e31f1e16240db73449f0500afdbbe3a70da457cc5460ff1690565b610bb8611348565b600160a060020a03163314610bcc57600080fd5b610bd461127a565b811180610bdf575080155b1515610bea57600080fd5b7f21dbcab260e413c20dc13c28b7db95e2b423d1135f42bb8b7d5214a92270d237600090815260209081527fadd938dbd083a16bae12238cd914fca0afc7a30edb55b1cd5c7f1823f1b0e4218290556040805183815290517f9bebf928b90863f24cc31f726a3a7545efd409f1dcf552301b1ee3710da70d3b929181900390910190a150565b62015180420490565b7f582ed8fd0000000000000000000000000000000000000000000000000000000090565b7f21dbcab260e413c20dc13c28b7db95e2b423d1135f42bb8b7d5214a92270d23760009081526020527fadd938dbd083a16bae12238cd914fca0afc7a30edb55b1cd5c7f1823f1b0e4215490565b7f3db340e280667ee926fa8c51e8f9fcf88a0ff221a66d84d63b4778127d97d13960009081526020527ef98556deae64bbaa11436ee534ae029e85ed112aff9b71330af4c2d320eac95490565b60008060008360405160200180807f746f74616c45786563757465645065724461790000000000000000000000000081525060130182815260200191505060405160208183030381529060405260405180828051906020019080838360208310610b1e5780518252601f199092019160209182019101610aff565b6040805160048152602481018252602081018051600160e060020a03167f6fde8202000000000000000000000000000000000000000000000000000000001781529151815160009330939291829190808383895b83811015610e1f578181015183820152602001610e07565b50505050905090810190601f168015610e4c5780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af19150501580610ede575030600160a060020a0316636fde82026040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015610ea657600080fd5b505af1158015610eba573d6000803e3d6000fd5b505050506040513d6020811015610ed057600080fd5b5051600160a060020a031633145b80610ee857503330145b1515610ef357600080fd5b610f438989896003806020026040519081016040528092919082600360200280828437505060408051808201825293508d9250600291508390839080828437820191505050505089898989612397565b610f4b612410565b610f53610b5f565b9998505050505050505050565b60008060008030600160a060020a0316636fde82026040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015610fa457600080fd5b505af1158015610fb8573d6000803e3d6000fd5b505050506040513d6020811015610fce57600080fd5b5051600160a060020a03163314610fe457600080fd5b30319350610ff0610ceb565b9250828411610ffe57600080fd5b828403915061100b61139f565b90506000811161101a57600080fd5b80821115611026578091505b611037611031610c70565b83611c5d565b61104a610940848463ffffffff611d2616565b611055858684611d85565b5050505050565b6000600460008360405160200180807f6d65737361676546697865640000000000000000000000000000000000000000815250600c0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106110e15780518252601f1990920191602091820191016110c2565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1695945050505050565b610a48816106b3565b611136611348565b600160a060020a0316331461114a57600080fd5b610a4881612467565b7f4a6a899679f26b73530d8cf1001e83b6f7702e04b6fdb98f3c62dc7e47e041a560009081526020527f1ab29a5cca988aee50edccdd61c5bcaa7ad4b29a03b7ee50f298ceccfe14cc4e5490565b600160a060020a03821615156111b657600080fd5b6109508282612503565b6111c8611348565b600160a060020a031633146111dc57600080fd5b610a48816125a1565b7f98aa806e31e94a687a31c65769cb99670064dd7f5a87526da075c5fb4eab988060005260026020527f0c1206883be66049a02d4937078367c00b3d71dd1a9465df969363c6ddeac96d54600160a060020a031690565b6000806112538361093461124e610c70565b610d38565b90508061125e610c9d565b10158015611273575061126f61127a565b8311155b9392505050565b7fc0ed44c192c86d1cc1ba51340b032c2766b4a2b0041031de13c46dd7104888d560009081526020527ff8e983ee86e5e377e9e34c9131b266382c3f04113d20de077f9e12663c7a646b5490565b6112d061199f565b600160a060020a031633146112e457600080fd5b6112ec6111e5565b600160a060020a03166112fd611f17565b600160a060020a03161461131057600080fd5b6113198161123c565b1561133e5761132f611329610c70565b82612618565b611339828261269e565b610950565b6109508282612906565b7f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c060005260026020527fb7802e97e87ef2842a6cce7da7ffaeaedaa2f61a6a7870b23d9d01fc9b73712e54600160a060020a031690565b60008060008060006113af611c0f565b93506113b9611153565b92506113cb6113c6610c70565b610aa2565b91508183116113db5760006113df565b8183035b90508084106113ee57806113f0565b835b94505050505090565b6000606061140561199f565b600160a060020a031663cb08a10c846040518263ffffffff1660e060020a028152600401808260001916600019168152602001915050602060405180830381600087803b15801561145557600080fd5b505af1158015611469573d6000803e3d6000fd5b505050506040513d602081101561147f57600080fd5b50511561148b57600080fd5b3061149461199f565b600160a060020a0316633f9a8e7e856040518263ffffffff1660e060020a028152600401808260001916600019168152602001915050602060405180830381600087803b1580156114e457600080fd5b505af11580156114f8573d6000803e3d6000fd5b505050506040513d602081101561150e57600080fd5b5051600160a060020a03161461152357600080fd5b61152b6111e5565b600160a060020a031661153c61199f565b600160a060020a0316634a610b04856040518263ffffffff1660e060020a028152600401808260001916600019168152602001915050602060405180830381600087803b15801561158c57600080fd5b505af11580156115a0573d6000803e3d6000fd5b505050506040513d60208110156115b657600080fd5b5051600160a060020a0316146115cb57600080fd5b5050604080516024808201849052825180830390910181526044909101909152602081018051600160e060020a03167f0950d515000000000000000000000000000000000000000000000000000000009081179091529061162a61199f565b600160a060020a031663dc8601b36116406111e5565b836116496118b9565b6040518463ffffffff1660e060020a0281526004018084600160a060020a0316600160a060020a0316815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156116b657818101518382015260200161169e565b50505050905090810190601f1680156116e35780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561170457600080fd5b505af1158015611718573d6000803e3d6000fd5b505050506040513d602081101561105557600080fd5b6001806000909192565b611740611348565b600160a060020a0316331461175457600080fd5b60008111801561176a5750611767611153565b81105b801561177c5750611779611c0f565b81105b151561178757600080fd5b7fbbb088c505d18e049d114c7c91f11724e69c55ad6c5397e2b929e68b41fa05d160009081526020527f8df5c48c6b6e11d97548adc824ba0c99103ec09830fa5d53a179984085e6eaa055565b6117dc611348565b600160a060020a031633146117f057600080fd5b610a488161290b565b611801611348565b600160a060020a0316331461181557600080fd5b61181d611c0f565b811180611828575080155b151561183357600080fd5b7f4a6a899679f26b73530d8cf1001e83b6f7702e04b6fdb98f3c62dc7e47e041a5600090815260209081527f1ab29a5cca988aee50edccdd61c5bcaa7ad4b29a03b7ee50f298ceccfe14cc4e8290556040805183815290517fad4123ae17c414d9c6d2fec478b402e6b01856cc250fd01fbfd252fda0089d3c929181900390910190a150565b7f2dfd6c9f781bb6bbb5369c114e949b69ebb440ef3d4dd6b2836225eb1dc3a2be60009081526020527f2de0d2cdc19d356cb53b5984f91bfd3b31fe0c678a0d190a6db39274bb34753f5490565b61190f611348565b600160a060020a0316331461192357600080fd5b8015806119475750611933611a9b565b811180156119475750611944611153565b81105b151561195257600080fd5b7f0f8803acad17c63ee38bf2de71e1888bc7a079a6f73658e274b08018bea4e29c60009081526020527f9de0f81379b4d8e60fe509315d071b56e7b732abaf193e74e0d15808b0951d0955565b7f811bbb11e8899da471f0e69a3ed55090fc90215227fc5fb1cb0d6e962ea7b74f60005260026020527fb4ed64697d3ef8518241966f7c6f28b0d72f20f51198717d198d2d55076c593d54600160a060020a031690565b7f1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee560009081526020527fd5c78dd9468716ca9bb96be25d56436811b20aab3523a9904b12deef1cab239d5490565b7f779a349c5bee7817f04c960f525ee3e2f2516078c38c68a3149787976ee837e560005260026020527fc155b21a14c4592b97825e495fbe0d2705fb46420018cac5bfa7a09c43fae51754600160a060020a031690565b7fbbb088c505d18e049d114c7c91f11724e69c55ad6c5397e2b929e68b41fa05d160009081526020527f8df5c48c6b6e11d97548adc824ba0c99103ec09830fa5d53a179984085e6eaa05490565b600080611afb836109346113c6610c70565b905080611b06611153565b10158015611b1b5750611b17611c0f565b8311155b80156112735750611b2a611a9b565b9092101592915050565b611b3c611348565b600160a060020a03163314611b5057600080fd5b611b58610c9d565b8110611b6357600080fd5b7fc0ed44c192c86d1cc1ba51340b032c2766b4a2b0041031de13c46dd7104888d560009081526020527ff8e983ee86e5e377e9e34c9131b266382c3f04113d20de077f9e12663c7a646b55565b611bb8611348565b600160a060020a03163314611bcc57600080fd5b600160a060020a0381161515611be157600080fd5b610a4881612996565b611bf2611348565b600160a060020a03163314611c0657600080fd5b610a4881612a58565b7f0f8803acad17c63ee38bf2de71e1888bc7a079a6f73658e274b08018bea4e29c60009081526020527f9de0f81379b4d8e60fe509315d071b56e7b732abaf193e74e0d15808b0951d095490565b611c6a8161093484610aa2565b6000808460405160200180807f746f74616c5370656e74506572446179000000000000000000000000000000008152506010018281526020019150506040516020818303038152906040526040518082805190602001908083835b60208310611ce45780518252601f199092019160209182019101611cc5565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020939093555050505050565b81810182811015611d3357fe5b92915050565b7f3db340e280667ee926fa8c51e8f9fcf88a0ff221a66d84d63b4778127d97d13960009081526020527ef98556deae64bbaa11436ee534ae029e85ed112aff9b71330af4c2d320eac955565b60408051600160a060020a03841660248201526044808201849052825180830390910181526064909101909152602081018051600160e060020a03167f8b6c035400000000000000000000000000000000000000000000000000000000908117909152906000611df361199f565b600160a060020a031663dc8601b3611e096111e5565b84611e126118b9565b6040518463ffffffff1660e060020a0281526004018084600160a060020a0316600160a060020a0316815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611e7f578181015183820152602001611e67565b50505050905090810190601f168015611eac5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015611ecd57600080fd5b505af1158015611ee1573d6000803e3d6000fd5b505050506040513d6020811015611ef757600080fd5b50519050611f058185612ab9565b611f0f8187612b3b565b505050505050565b6000611f2161199f565b600160a060020a031663d67bdd256040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015611f5e57600080fd5b505af1158015611f72573d6000803e3d6000fd5b505050506040513d6020811015611f8857600080fd5b5051905090565b6000600260008360405160200180807f6d657373616765526563697069656e740000000000000000000000000000000081525060100182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106120145780518252601f199092019160209182019101611ff5565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a031695945050505050565b60008060008360405160200180807f6d65737361676556616c75650000000000000000000000000000000000000000815250600c01826000191660001916815260200191505060405160208183030381529060405260405180828051906020019080838360208310610b1e5780518252601f199092019160209182019101610aff565b6001600460008360405160200180807f6d65737361676546697865640000000000000000000000000000000000000000815250600c0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106121665780518252601f199092019160209182019101612147565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff19169415159490941790935550505050565b60006121d0610940836121c4610ceb565b9063ffffffff612c2916565b6121d8610a4b565b9050600160a060020a03811615801590612275575080600160a060020a031663fbac3951846040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801561224857600080fd5b505af115801561225c573d6000803e3d6000fd5b505050506040513d602081101561227257600080fd5b50515b156122fd5780600160a060020a0316636cac044a8385612293612c3b565b6040805160e060020a63ffffffff8716028152600160a060020a039093166004840152602483019190915251604480830192600092919082900301818588803b1580156122df57600080fd5b505af11580156122f3573d6000803e3d6000fd5b5050505050612307565b6123078383612c82565b505050565b61231581612ce3565b151561232057600080fd5b7f811bbb11e8899da471f0e69a3ed55090fc90215227fc5fb1cb0d6e962ea7b74f60005260026020527fb4ed64697d3ef8518241966f7c6f28b0d72f20f51198717d198d2d55076c593d805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b61239f610b5f565b156123a957600080fd5b600160a060020a03821615156123be57600080fd5b6123c78861230c565b6123d0876125a1565b6123d984612a58565b6123e286612ceb565b6123eb85612e48565b6123f483612f1d565b6123fd81612467565b61240682612996565b5050505050505050565b7f0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba60005260046020527f078d888f9b66f3f8bfa10909e31f1e16240db73449f0500afdbbe3a70da457cc805460ff19166001179055565b600160a060020a0381161580612481575061248181612ce3565b151561248c57600080fd5b7f779a349c5bee7817f04c960f525ee3e2f2516078c38c68a3149787976ee837e560005260026020527fc155b21a14c4592b97825e495fbe0d2705fb46420018cac5bfa7a09c43fae517805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b30600160a060020a0316636fde82026040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561254157600080fd5b505af1158015612555573d6000803e3d6000fd5b505050506040513d602081101561256b57600080fd5b5051600160a060020a0316331461258157600080fd5b80600160a060020a038116151561259757600080fd5b6123078383612f86565b7f98aa806e31e94a687a31c65769cb99670064dd7f5a87526da075c5fb4eab988060005260026020527f0c1206883be66049a02d4937078367c00b3d71dd1a9465df969363c6ddeac96d805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6126258161093484610d38565b6000808460405160200180807f746f74616c45786563757465645065724461790000000000000000000000000081525060130182815260200191505060405160208183030381529060405260405180828051906020019080838360208310611ce45780518252601f199092019160209182019101611cc5565b60008060008060006126af86612fa9565b94506126c0610940866121c4610ceb565b6126c8612c3b565b93506126d2610a4b565b9250600160a060020a0383161580159061276f575082600160a060020a031663fbac3951886040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801561274257600080fd5b505af1158015612756573d6000803e3d6000fd5b505050506040513d602081101561276c57600080fd5b50515b156127fe57604080517f6cac044a000000000000000000000000000000000000000000000000000000008152600160a060020a03898116600483015260248201879052915191851691636cac044a918891604480830192600092919082900301818588803b1580156127e057600080fd5b505af11580156127f4573d6000803e3d6000fd5b50505050506128fd565b612806611a44565b9150600160a060020a038216156128b25781600160a060020a03166399a5d747866040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561286057600080fd5b505af1158015612874573d6000803e3d6000fd5b505050506040513d602081101561288a57600080fd5b5051905080156128b25761289f828286612fbc565b6128af858263ffffffff612c2916565b94505b6128bc8786612c82565b6040805186815290518591600160a060020a038a16917f2f9a6098d4503a127779ba975f5f6b04f842362b1809f346989e9abc0b4dedb69181900360200190a35b50505050505050565b600080fd5b61291481612ce3565b151561291f57600080fd5b7f9ba5a09a13321d5fc0d3150bbf4489a02b9b881bf70e2fc6639c91e8c5ce714c60005260026020527f87f07cf898f772bd3ff661aa30d2354333eefbd852e374d9021ef7a3463e81fd805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e06129bf611348565b60408051600160a060020a03928316815291841660208301528051918290030190a17f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c060005260026020527fb7802e97e87ef2842a6cce7da7ffaeaedaa2f61a6a7870b23d9d01fc9b73712e805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b612a606130db565b811115612a6c57600080fd5b7f2dfd6c9f781bb6bbb5369c114e949b69ebb440ef3d4dd6b2836225eb1dc3a2be60009081526020527f2de0d2cdc19d356cb53b5984f91bfd3b31fe0c678a0d190a6db39274bb34753f55565b806000808460405160200180807f6d65737361676556616c75650000000000000000000000000000000000000000815250600c01826000191660001916815260200191505060405160208183030381529060405260405180828051906020019080838360208310611ce45780518252601f199092019160209182019101611cc5565b80600260008460405160200180807f6d657373616765526563697069656e740000000000000000000000000000000081525060100182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b60208310612bbf5780518252601f199092019160209182019101612ba0565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0395909516949094179093555050505050565b600082821115612c3557fe5b50900390565b6000612c4561199f565b600160a060020a031663669f618b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015611f5e57600080fd5b604051600160a060020a0383169082156108fc029083906000818181858888f193505050501515610950578082612cb76132ff565b600160a060020a039091168152604051908190036020019082f080158015611055573d6000803e3d6000fd5b6000903b1190565b60408101516000108015612d06575060408101516020820151115b8015612d16575060208101518151115b1515612d2157600080fd5b80517f4a6a899679f26b73530d8cf1001e83b6f7702e04b6fdb98f3c62dc7e47e041a5600090815260208181527f1ab29a5cca988aee50edccdd61c5bcaa7ad4b29a03b7ee50f298ceccfe14cc4e92909255908201517f0f8803acad17c63ee38bf2de71e1888bc7a079a6f73658e274b08018bea4e29c82527f9de0f81379b4d8e60fe509315d071b56e7b732abaf193e74e0d15808b0951d095560408201517fbbb088c505d18e049d114c7c91f11724e69c55ad6c5397e2b929e68b41fa05d182527f8df5c48c6b6e11d97548adc824ba0c99103ec09830fa5d53a179984085e6eaa0557fad4123ae17c414d9c6d2fec478b402e6b01856cc250fd01fbfd252fda0089d3c9082905b60200201516040518082815260200191505060405180910390a150565b8051602082015110612e5957600080fd5b80517f21dbcab260e413c20dc13c28b7db95e2b423d1135f42bb8b7d5214a92270d237600090815260208181527fadd938dbd083a16bae12238cd914fca0afc7a30edb55b1cd5c7f1823f1b0e42192909255908201517fc0ed44c192c86d1cc1ba51340b032c2766b4a2b0041031de13c46dd7104888d582527ff8e983ee86e5e377e9e34c9131b266382c3f04113d20de077f9e12663c7a646b557f9bebf928b90863f24cc31f726a3a7545efd409f1dcf552301b1ee3710da70d3b908290612e2b565b604c1981138015612f2e5750604d81125b1515612f3957600080fd5b7f1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee560009081526020527fd5c78dd9468716ca9bb96be25d56436811b20aab3523a9904b12deef1cab239d55565b600160a060020a0382161515612f9f5761133981613122565b610950828261312e565b6000611d3382612fb76119f6565b6131d2565b612fc6838361321d565b604080513060248201526044810184905260606064820152600060848201819052825180830360a401815260c49092018352602082018051600160e060020a03167fa4c0ed360000000000000000000000000000000000000000000000000000000017815292518251600160a060020a038816949192839291908190849084905b8381101561305f578181015183820152602001613047565b50505050905090810190601f16801561308c5780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af150506040805184815290518392507f681bf203c0adea167c3149ed45e4ec409535394f7bd8941e675f26d1b1a4b6569181900360200190a2505050565b60006130e561199f565b600160a060020a031663e5789d036040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015611f5e57600080fd5b30316109508282612c82565b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290518391600091600160a060020a038416916370a0823191602480830192602092919082900301818787803b15801561319357600080fd5b505af11580156131a7573d6000803e3d6000fd5b505050506040513d60208110156131bd57600080fd5b505190506131cc848483613227565b50505050565b60008115156131e2575081611d33565b6000821315613206576131ff83600a84900a63ffffffff6132c116565b9050611d33565b611273836000849003600a0a63ffffffff6132ea16565b6109508282612c82565b60408051600160a060020a0384166024820152604480820184905282518083039091018152606490910190915260208181018051600160e060020a03167fa9059cbb000000000000000000000000000000000000000000000000000000001781528251606093600093909290918491828a5af16000519350839250808015612906575050600083511115611f0f57811515611f0f57600080fd5b60008215156132d257506000611d33565b508181028183828115156132e257fe5b0414611d3357fe5b600081838115156132f757fe5b049392505050565b60405160218061330f833901905600608060405260405160208060218339810160405251600160a060020a038116ff00a165627a7a723058200e0ee8af1134ef49a6fc2ed2f53e83e2ba5ab0917cd8998a5e76e185b3ca51b10029