Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
XDaiForeignBridge
Compiler Version
v0.4.24+commit.e67f0147
Optimization Enabled:
Yes with 10 runs
Other Settings:
constantinople EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity 0.4.24;
import "./ForeignBridgeErcToNative.sol";
import "./SavingsDaiConnector.sol";
import "../GSNForeignERC20Bridge.sol";
import "../../interfaces/IDaiUsds.sol";
contract XDaiForeignBridge is ForeignBridgeErcToNative, SavingsDaiConnector, GSNForeignERC20Bridge {
address public constant DAI_USDS = 0x3225737a9Bbb6473CB4a45b7244ACa2BeFdB276A;
address public constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address public constant USDS = 0xdC035D45d973E3EC169d2276DDab16f1e407384F;
function initialize(
address _validatorContract,
address _erc20token,
uint256 _requiredBlockConfirmations,
uint256 _gasPrice,
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = _dailyLimit, 1 = _maxPerTx, 2 = _minPerTx ]
uint256[2] _homeDailyLimitHomeMaxPerTxArray, //[ 0 = _homeDailyLimit, 1 = _homeMaxPerTx ]
address _owner,
int256 _decimalShift,
address _bridgeOnOtherSide
) external onlyRelevantSender returns (bool) {
require(!isInitialized());
require(AddressUtils.isContract(_validatorContract));
require(_erc20token == address(daiToken()));
require(_decimalShift == 0);
addressStorage[VALIDATOR_CONTRACT] = _validatorContract;
uintStorage[DEPLOYED_AT_BLOCK] = block.number;
_setRequiredBlockConfirmations(_requiredBlockConfirmations);
_setGasPrice(_gasPrice);
_setLimits(_dailyLimitMaxPerTxMinPerTxArray);
_setExecutionLimits(_homeDailyLimitHomeMaxPerTxArray);
_setOwner(_owner);
_setBridgeContractOnOtherSide(_bridgeOnOtherSide);
setInitialize();
return isInitialized();
}
/**
* @dev return the address of USDS
*/
function erc20token() public view returns (ERC20) {
return ERC20(USDS);
}
/**
* @dev one time function to be called during bridge upgrade
*/
function swapSDAIToUSDS() public {
bytes32 isUSDSBridgeUpgrade = keccak256("upgrade_DAI_to_USDS");
require(!boolStorage[isUSDSBridgeUpgrade], "USDS bridge ugprade completed");
address sDAI = 0x83F20F44975D03b1b09e64809B757c47f942BEeA;
// withdraw all sDAI into DAI
uint256 maxWithdrawable = ISavingsDai(sDAI).maxWithdraw(address(this));
ISavingsDai(sDAI).withdraw(maxWithdrawable, address(this), address(this));
// disableInterest for DAI
_setInvestedAmount(DAI, 0);
_setInterestEnabled(DAI, false);
_setMinCashThreshold(DAI, 0);
_setMinInterestPaid(DAI, 0);
// swap DAI -> USDS
uint256 remainDAI = ERC20(DAI).balanceOf(address(this));
ERC20(DAI).approve(DAI_USDS, remainDAI);
IDaiUsds(DAI_USDS).daiToUsds(address(this), remainDAI);
boolStorage[isUSDSBridgeUpgrade] = true;
}
/**
* @dev Withdraws USDS from sUSDS vault to the bridge up to min cash threshold
*/
function refillBridge() external {
uint256 currentBalance = ERC20(USDS).balanceOf(address(this));
uint256 minThreshold = minCashThreshold(USDS);
require(currentBalance < minThreshold, "Bridge is Filled");
uint256 withdrawAmount = minThreshold - currentBalance;
_withdraw(USDS, withdrawAmount);
}
/**
* @dev Invests the USDS into the sUSDS Vault.
*/
function investDai() external {
invest(USDS);
}
/**
* @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 {
// Since bridged tokens are locked at this contract, it is not allowed to claim them with the use of claimTokens function
address bridgedToken = USDS;
address sUSDS = 0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD;
require(_token != bridgedToken, "Can't claim USDS");
require(_token != sUSDS || !isInterestEnabled(bridgedToken), "Can't claim sUSDS");
claimValues(_token, _to);
}
/**
* @dev Withdraws the USDS tokens if they are mistakenly sent to this contract after the Hashi integration, as the Transfer event will no longer be supported.
* @param _to address of the tokens/coins receiver.
*/
function recoverLegacyTransfer(address _to, uint256 recoverAmount) external onlyIfUpgradeabilityOwner {
uint256 currentBalance = ERC20(USDS).balanceOf(this);
uint256 minThreshold = minCashThreshold(USDS);
require(recoverAmount < currentBalance, "invalid withdraw balance");
if (currentBalance - recoverAmount < minThreshold) {
// need to fill the bridge to ensure enough USDS for withdrawal
uint256 withdrawAmount = minThreshold + recoverAmount - currentBalance;
_withdraw(USDS, withdrawAmount);
}
ERC20(USDS).transfer(_to, recoverAmount);
}
/// @dev this function returns DAI/USDS based on _tokenAddress
function onExecuteMessage(address _recipient, uint256 _amount, bytes32, /*_nonce*/ address _tokenAddress)
internal
returns (bool)
{
addTotalExecutedPerDay(getCurrentDay(), _amount);
ERC20 token = ERC20(USDS);
ensureEnoughTokens(token, _amount);
if (_tokenAddress == DAI) {
token.approve(DAI_USDS, _amount);
IDaiUsds(DAI_USDS).usdsToDai(address(this), _amount);
return ERC20(DAI).transfer(_recipient, _amount);
} else if (_tokenAddress == USDS) {
return token.transfer(_recipient, _amount);
} else {
revert();
}
}
function onExecuteMessageGSN(address recipient, uint256 amount, uint256 fee) internal returns (bool) {
ensureEnoughTokens(ERC20(USDS), amount);
return super.onExecuteMessageGSN(recipient, amount, fee);
}
function ensureEnoughTokens(ERC20 token, uint256 amount) internal {
uint256 currentBalance = token.balanceOf(address(this));
if (currentBalance < amount) {
uint256 withdrawAmount = (amount - currentBalance).add(minCashThreshold(address(token)));
_withdraw(address(token), withdrawAmount);
}
}
}pragma solidity 0.4.24;
import "../ERC20Bridge.sol";
import "../OtherSideBridgeStorage.sol";
contract ForeignBridgeErcToNative is ERC20Bridge, OtherSideBridgeStorage {
function initialize(
address _validatorContract,
address _erc20token,
uint256 _requiredBlockConfirmations,
uint256 _gasPrice,
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = _dailyLimit, 1 = _maxPerTx, 2 = _minPerTx ]
uint256[2] _homeDailyLimitHomeMaxPerTxArray, //[ 0 = _homeDailyLimit, 1 = _homeMaxPerTx ]
address _owner,
int256 _decimalShift,
address _bridgeOnOtherSide
) external onlyRelevantSender returns (bool) {
require(!isInitialized());
require(AddressUtils.isContract(_validatorContract));
addressStorage[VALIDATOR_CONTRACT] = _validatorContract;
setErc20token(_erc20token);
uintStorage[DEPLOYED_AT_BLOCK] = block.number;
_setRequiredBlockConfirmations(_requiredBlockConfirmations);
_setGasPrice(_gasPrice);
_setLimits(_dailyLimitMaxPerTxMinPerTxArray);
_setExecutionLimits(_homeDailyLimitHomeMaxPerTxArray);
_setDecimalShift(_decimalShift);
_setOwner(_owner);
_setBridgeContractOnOtherSide(_bridgeOnOtherSide);
setInitialize();
return isInitialized();
}
function getBridgeMode() external pure returns (bytes4 _data) {
return 0x18762d46; // bytes4(keccak256(abi.encodePacked("erc-to-native-core")))
}
/**
* @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 {
// Since bridged tokens are locked at this contract, it is not allowed to claim them with the use of claimTokens function
require(_token != address(erc20token()), "Bridged Token is disallowed");
claimValues(_token, _to);
}
function onExecuteMessage(
address _recipient,
uint256 _amount,
bytes32, /*_nonce*/
address _tokenAddress
) internal returns (bool) {
require(_tokenAddress == address(erc20token()));
addTotalExecutedPerDay(getCurrentDay(), _amount);
return erc20token().transfer(_recipient, _unshiftValue(_amount));
}
function onFailedMessage(address, uint256, bytes32) internal {
revert();
}
function relayTokens(address _receiver, uint256 _amount) public {
require(_receiver != bridgeContractOnOtherSide(), "Relayed to Bridge address");
require(_receiver != address(0), "Relayed to Null address");
require(_receiver != address(this), "Relayed to this address");
require(_amount > 0, "Relayed zero funds");
require(withinLimit(_amount), "Exceeds bridge daily limit");
addTotalSpentPerDay(getCurrentDay(), _amount);
erc20token().transferFrom(msg.sender, address(this), _amount);
_emitUserRequestForAffirmationIncreaseNonceAndMaybeSendDataWithHashi(_receiver, _amount);
}
}pragma solidity 0.4.24;
import "./InterestConnector.sol";
import "../../interfaces/ISavingsDai.sol";
/**
* @title SavingsDaiConnector
* @dev After the usds upgrade, this contract deposit locked USDS into Sky's SSR.
* @dev The contract and functions name in this contract remains unchanged but the value of daiToken() and sDaiToken() are changed to Usds and sUsds address respectively.
* @dev https://forum.gnosis.io/t/gip-118-should-sdai-be-replaced-by-susds-in-the-bridge/9354
* @dev This must never be deployed standalone and only as an interface to interact with the sUSDS from the InterestConnector
*/
contract SavingsDaiConnector is InterestConnector {
/**
* @dev After the usds upgrade, this function returns the address of the USDS token in the Ethereum Mainnet instead of DAI token address.
* @dev To minimize the changes on the bridge contract itself, the same function name is used but the address is changed. One should be aware when interacting with the contract.
*/
function daiToken() public pure returns (ERC20) {
return ERC20(0xdC035D45d973E3EC169d2276DDab16f1e407384F);
}
/**
* @dev After the usds upgrade, this function returns the address of the sUSDS token in the Ethereum Mainnet instead of sDAI token address.
* @dev To minimize the changes on the bridge contract itself, the same function name is used but the address is changed. One should be aware when interacting with the contract.
*/
function sDaiToken() public pure returns (ISavingsDai) {
return ISavingsDai(0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD);
}
/**
* @dev Tells the current earned interest amount.
* @param _token address of the underlying token contract.
* @return total amount of interest that can be withdrawn now.
*/
function interestAmount(address _token) public view returns (uint256) {
require(_token == 0xdC035D45d973E3EC169d2276DDab16f1e407384F, "Not USDS");
uint256 underlyingBalance = ISavingsDai(0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD).maxWithdraw(address(this));
// 1 DAI is reserved for possible truncation/round errors
uint256 invested = investedAmount(_token) + 1 ether;
return underlyingBalance > invested ? underlyingBalance - invested : 0;
}
/**
* @dev Tells if interest earning is supported for the specific token contract.
* @param _token address of the token contract.
* @return true, if interest earning is supported.
*/
function _isInterestSupported(address _token) internal pure returns (bool) {
return _token == 0xdC035D45d973E3EC169d2276DDab16f1e407384F;
}
/**
* @dev Invests the given amount of DAI to the sDAI Vault.
* Deposits _amount of _token into the sDAI vault.
* @param _token address of the token contract.
* @param _amount amount of tokens to invest.
*/
function _invest(address _token, uint256 _amount) internal {
require(_token == 0xdC035D45d973E3EC169d2276DDab16f1e407384F, "not USDS");
ERC20(0xdC035D45d973E3EC169d2276DDab16f1e407384F).approve(0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD, _amount);
require(
ISavingsDai(0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD).deposit(_amount, address(this)) > 0,
"Failed to deposit"
);
}
/**
* @dev Withdraws at least the given amount of USDS from the sUSDS vault contract.
* Withdraws the _amount of _token from the sUSDS vault.
* @param _token address of the token contract.
* @param _amount minimal amount of tokens to withdraw.
*/
function _withdrawTokens(address _token, uint256 _amount) internal {
require(_token == 0xdC035D45d973E3EC169d2276DDab16f1e407384F, "not USDS");
require(
ISavingsDai(0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD).withdraw(_amount, address(this), address(this)) > 0,
"Failed to withdraw"
);
}
/**
* @dev Previews a withdraw of the given amount of DAI from the sDAI vault contract.
* Previews withdrawing the _amount of _token from the sDAI vault.
* @param _token address of the token contract.
* @param _amount minimal amount of tokens to withdraw.
*/
function previewWithdraw(address _token, uint256 _amount) public view returns (uint256) {
require(_token == 0xdC035D45d973E3EC169d2276DDab16f1e407384F, "not USDS");
return ISavingsDai(0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD).previewWithdraw(_amount);
}
}pragma solidity 0.4.24;
import "./BasicForeignBridge.sol";
import "./ERC20Bridge.sol";
import "../gsn/BaseRelayRecipient.sol";
import "../gsn/interfaces/IKnowForwarderAddress.sol";
contract GSNForeignERC20Bridge is BasicForeignBridge, ERC20Bridge, BaseRelayRecipient, IKnowForwarderAddress {
bytes32 internal constant PAYMASTER = 0xfefcc139ed357999ed60c6a013947328d52e7d9751e93fd0274a2bfae5cbcb12; // keccak256(abi.encodePacked("paymaster"))
bytes32 internal constant TRUSTED_FORWARDER = 0x222cb212229f0f9bcd249029717af6845ea3d3a84f22b54e5744ac25ef224c92; // keccak256(abi.encodePacked("trustedForwarder"))
function versionRecipient() external view returns (string memory) {
return "1.0.1";
}
function getTrustedForwarder() external view returns (address) {
return addressStorage[TRUSTED_FORWARDER];
}
function setTrustedForwarder(address _trustedForwarder) public onlyOwner {
addressStorage[TRUSTED_FORWARDER] = _trustedForwarder;
}
function isTrustedForwarder(address forwarder) public view returns (bool) {
return forwarder == addressStorage[TRUSTED_FORWARDER];
}
function setPayMaster(address _paymaster) public onlyOwner {
addressStorage[PAYMASTER] = _paymaster;
}
/**
* @param message same as in `executeSignatures`
* @param signatures same as in `executeSignatures`
* @param maxTokensFee maximum amount of foreign tokens that user allows to take
* as a commission
*/
function executeSignaturesGSN(bytes message, bytes signatures, uint256 maxTokensFee) external {
// Allow only forwarder calls
require(isTrustedForwarder(msg.sender), "invalid forwarder");
Message.hasEnoughValidSignatures(message, signatures, validatorContract(), false);
address recipient;
uint256 amount;
bytes32 txHash;
address contractAddress;
address tokenAddress;
(recipient, amount, txHash, contractAddress, tokenAddress) = Message.parseMessage(message);
require(tokenAddress == address(erc20token()));
if (withinExecutionLimit(amount)) {
require(maxTokensFee <= amount);
require(contractAddress == address(this));
require(!relayedMessages(txHash));
setRelayedMessages(txHash, true);
require(onExecuteMessageGSN(recipient, amount, maxTokensFee));
emit RelayedMessage(recipient, amount, txHash);
} else {
onFailedMessage(recipient, amount, txHash);
}
}
function onExecuteMessageGSN(address recipient, uint256 amount, uint256 fee) internal returns (bool) {
addTotalExecutedPerDay(getCurrentDay(), amount);
// Send maxTokensFee to paymaster
ERC20 token = erc20token();
bool first = token.transfer(addressStorage[PAYMASTER], fee);
bool second = token.transfer(recipient, amount - fee);
return first && second;
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.4.24;
interface IDaiUsds {
event DaiToUsds(address indexed caller, address indexed usr, uint256 wad);
event UsdsToDai(address indexed caller, address indexed usr, uint256 wad);
function daiToUsds(address usr, uint256 wad) external;
function usdsToDai(address usr, uint256 wad) external;
function dai() external view returns (address);
function usds() external view returns (address);
}pragma solidity 0.4.24;
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import "openzeppelin-solidity/contracts/AddressUtils.sol";
import "./BasicForeignBridge.sol";
contract ERC20Bridge is BasicForeignBridge {
bytes32 internal constant ERC20_TOKEN = 0x15d63b18dbc21bf4438b7972d80076747e1d93c4f87552fe498c90cbde51665e; // keccak256(abi.encodePacked("erc20token"))
function erc20token() public view returns (ERC20) {
return ERC20(addressStorage[ERC20_TOKEN]);
}
function setErc20token(address _token) internal {
require(AddressUtils.isContract(_token));
addressStorage[ERC20_TOKEN] = _token;
}
function relayTokens(address _receiver, uint256 _amount) public {
require(_receiver != address(0), "Receiver can't be Null");
require(_receiver != address(this), "Receiver can't be the Bridge");
require(_amount > 0, "Relayed zero tokens");
require(withinLimit(_amount), "Relayed above limit");
addTotalSpentPerDay(getCurrentDay(), _amount);
erc20token().transferFrom(msg.sender, address(this), _amount);
_emitUserRequestForAffirmationIncreaseNonceAndMaybeSendDataWithHashi(_receiver, _amount);
}
function _relayInterest(address _receiver, uint256 _amount) internal {
require(_receiver != address(0), "Receiver can't be Null");
require(_receiver != address(this), "Receiver can't be the Bridge");
require(_amount > 0, "Relayed zero tokens");
require(withinLimit(_amount), "Relayed above limit");
addTotalSpentPerDay(getCurrentDay(), _amount);
_emitUserRequestForAffirmationIncreaseNonceAndMaybeSendDataWithHashi(_receiver, _amount);
}
}pragma solidity 0.4.24;
import "../upgradeability/EternalStorage.sol";
contract OtherSideBridgeStorage is EternalStorage {
bytes32 internal constant BRIDGE_CONTRACT = 0x71483949fe7a14d16644d63320f24d10cf1d60abecc30cc677a340e82b699dd2; // keccak256(abi.encodePacked("bridgeOnOtherSide"))
function _setBridgeContractOnOtherSide(address _bridgeContract) internal {
require(_bridgeContract != address(0));
addressStorage[BRIDGE_CONTRACT] = _bridgeContract;
}
function bridgeContractOnOtherSide() internal view returns (address) {
return addressStorage[BRIDGE_CONTRACT];
}
}pragma solidity 0.4.24;
import "../Ownable.sol";
import "../ERC20Bridge.sol";
import "../../interfaces/IInterestReceiver.sol";
/**
* @title InterestConnector
* @dev This contract gives an abstract way of receiving interest on locked tokens.
*/
contract InterestConnector is Ownable, ERC20Bridge {
event PaidInterest(address indexed token, address to, uint256 value);
/**
* @dev Throws if interest is bearing not enabled.
* @param token address, for which interest should be enabled.
*/
modifier interestEnabled(address token) {
require(isInterestEnabled(token), "Interest not Enabled");
/* solcov ignore next */
_;
}
/**
* @dev Ensures that caller is an EOA.
* Functions with such modifier cannot be called from other contract (as well as from GSN-like approaches)
*/
modifier onlyEOA() {
// solhint-disable-next-line avoid-tx-origin
require(msg.sender == tx.origin, "Not EOA");
/* solcov ignore next */
_;
}
/**
* @dev Tells if interest earning was enabled for particular token.
* @return true, if interest bearing is enabled.
*/
function isInterestEnabled(address _token) public view returns (bool) {
return boolStorage[keccak256(abi.encodePacked("interestEnabled", _token))];
}
/**
* @dev Initializes interest receiving functionality.
* Only owner can call this method.
* @param _token address of the token for interest earning.
* @param _minCashThreshold minimum amount of underlying tokens that are not invested.
* @param _minInterestPaid minimum amount of interest that can be paid in a single call.
*/
function initializeInterest(
address _token,
uint256 _minCashThreshold,
uint256 _minInterestPaid,
address _interestReceiver
) external onlyOwner {
require(_isInterestSupported(_token), "Token not supported");
require(!isInterestEnabled(_token), "Interest already enabled");
_setInterestEnabled(_token, true);
_setMinCashThreshold(_token, _minCashThreshold);
_setMinInterestPaid(_token, _minInterestPaid);
_setInterestReceiver(_token, _interestReceiver);
}
/**
* @dev Sets minimum amount of tokens that cannot be invested.
* Only owner can call this method.
* @param _token address of the token contract.
* @param _minCashThreshold minimum amount of underlying tokens that are not invested.
*/
function setMinCashThreshold(address _token, uint256 _minCashThreshold) external onlyOwner {
_setMinCashThreshold(_token, _minCashThreshold);
}
/**
* @dev Tells minimum amount of tokens that are not being invested.
* @param _token address of the invested token contract.
* @return amount of tokens.
*/
function minCashThreshold(address _token) public view returns (uint256) {
return uintStorage[keccak256(abi.encodePacked("minCashThreshold", _token))];
}
/**
* @dev Sets lower limit for the paid interest amount.
* Only owner can call this method.
* @param _token address of the token contract.
* @param _minInterestPaid minimum amount of interest paid in a single call.
*/
function setMinInterestPaid(address _token, uint256 _minInterestPaid) external onlyOwner {
_setMinInterestPaid(_token, _minInterestPaid);
}
/**
* @dev Tells minimum amount of paid interest in a single call.
* @param _token address of the invested token contract.
* @return paid interest minimum limit.
*/
function minInterestPaid(address _token) public view returns (uint256) {
return uintStorage[keccak256(abi.encodePacked("minInterestPaid", _token))];
}
/**
* @dev Internal function that disables interest for locked funds.
* Only owner can call this method.
* @param _token of token to disable interest for.
*/
function disableInterest(address _token) external onlyOwner {
_withdraw(_token, uint256(-1));
_setInterestEnabled(_token, false);
}
/**
* @dev Tells configured address of the interest receiver.
* @param _token address of the invested token contract.
* @return address of the interest receiver.
*/
function interestReceiver(address _token) public view returns (address) {
return addressStorage[keccak256(abi.encodePacked("interestReceiver", _token))];
}
/**
* Updates the interest receiver address.
* Only owner can call this method.
* @param _token address of the invested token contract.
* @param _receiver new receiver address.
*/
function setInterestReceiver(address _token, address _receiver) external onlyOwner {
_setInterestReceiver(_token, _receiver);
}
/**
* @dev Pays collected interest for the specific underlying token to _reveicer contract on Gnosis Chain
* and reinvests amount claimed.
* Requires interest for the given token to be enabled.
* @param _token address of the token contract.
*/
function payInterest(address _token, uint256 _amount) external interestEnabled(_token) {
require(_token == address(erc20token()), "Not bridge Token");
uint256 claimable = interestAmount(_token);
uint256 interest = (_amount < claimable) ? _amount : claimable;
require(interest >= minInterestPaid(_token), "Collectable interest too low");
_setInvestedAmount(_token, investedAmount(_token).add(interest));
address receiver = interestReceiver(_token);
_relayInterest(receiver, interest);
emit PaidInterest(_token, receiver, interest);
}
/**
* @dev Tells the amount of underlying tokens that are currently invested.
* @param _token address of the token contract.
* @return amount of underlying tokens.
*/
function investedAmount(address _token) public view returns (uint256) {
return uintStorage[keccak256(abi.encodePacked("investedAmount", _token))];
}
/**
* @dev Invests all excess tokens.
* Requires interest for the given token to be enabled.
* @param _token address of the token contract considered.
*/
function invest(address _token) public interestEnabled(_token) {
uint256 balance = _selfBalance(_token);
uint256 minCash = minCashThreshold(_token);
require(balance > minCash, "Balance too Low");
uint256 amount = balance - minCash;
_setInvestedAmount(_token, investedAmount(_token).add(amount));
_invest(_token, amount);
}
/**
* @dev Internal function for transferring interest. Deprecated
* Calls a callback on the receiver, if it is a contract.
* @param _token address of the underlying token contract.
* @param _amount amount of collected tokens that should be sent.
*/
function _transferInterest(address _token, uint256 _amount) internal {
address receiver = interestReceiver(_token);
require(receiver != address(0), "Receiver can't be Null");
ERC20(_token).transfer(receiver, _amount);
if (AddressUtils.isContract(receiver)) {
IInterestReceiver(receiver).onInterestReceived(_token);
}
emit PaidInterest(_token, receiver, _amount);
}
/**
* @dev Internal function for setting interest enabled flag for some token.
* @param _token address of the token contract.
* @param _enabled true to enable interest earning, false to disable.
*/
function _setInterestEnabled(address _token, bool _enabled) internal {
boolStorage[keccak256(abi.encodePacked("interestEnabled", _token))] = _enabled;
}
/**
* @dev Internal function for setting the amount of underlying tokens that are currently invested.
* @param _token address of the token contract.
* @param _amount new amount of invested tokens.
*/
function _setInvestedAmount(address _token, uint256 _amount) internal {
uintStorage[keccak256(abi.encodePacked("investedAmount", _token))] = _amount;
}
/**
* @dev Internal function for withdrawing some amount of the invested tokens.
* Reverts if given amount cannot be withdrawn.
* @param _token address of the token contract withdrawn.
* @param _amount amount of requested tokens to be withdrawn.
*/
function _withdraw(address _token, uint256 _amount) internal {
uint256 invested = investedAmount(_token);
uint256 withdrawal = _amount > invested ? invested : _amount;
if (withdrawal == 0) return;
uint256 redeemed = _safeWithdrawTokens(_token, withdrawal);
_setInvestedAmount(_token, invested > redeemed ? invested - redeemed : 0);
}
/**
* @dev Internal function for safe withdrawal of invested tokens.
* Reverts if given amount cannot be withdrawn.
* Additionally verifies that at least _amount of tokens were withdrawn.
* @param _token address of the token contract withdrawn.
* @param _amount amount of requested tokens to be withdrawn.
*/
function _safeWithdrawTokens(address _token, uint256 _amount) private returns (uint256) {
uint256 balance = _selfBalance(_token);
_withdrawTokens(_token, _amount);
uint256 redeemed = _selfBalance(_token) - balance;
require(redeemed >= _amount, "Withdrawn less than Amount");
return redeemed;
}
/**
* @dev Internal function for setting minimum amount of tokens that cannot be invested.
* @param _token address of the token contract.
* @param _minCashThreshold minimum amount of underlying tokens that are not invested.
*/
function _setMinCashThreshold(address _token, uint256 _minCashThreshold) internal {
uintStorage[keccak256(abi.encodePacked("minCashThreshold", _token))] = _minCashThreshold;
}
/**
* @dev Internal function for setting lower limit for paid interest amount. Must be lower than DAILY_LIMIT and MAX_PER_TX
* @param _token address of the token contract.
* @param _minInterestPaid minimum amount of interest paid in a single call.
*/
function _setMinInterestPaid(address _token, uint256 _minInterestPaid) internal {
uintStorage[keccak256(abi.encodePacked("minInterestPaid", _token))] = _minInterestPaid;
}
/**
* @dev Internal function for setting interest receiver address.
* @param _token address of the invested token contract.
* @param _receiver address of the interest receiver.
*/
function _setInterestReceiver(address _token, address _receiver) internal {
require(_receiver != address(this), "Receiver can't be the Bridge");
addressStorage[keccak256(abi.encodePacked("interestReceiver", _token))] = _receiver;
}
/**
* @dev Tells this contract balance of some specific token contract
* @param _token address of the token contract.
* @return contract balance.
*/
function _selfBalance(address _token) internal view returns (uint256) {
return ERC20(_token).balanceOf(address(this));
}
function _isInterestSupported(address _token) internal pure returns (bool);
function _invest(address _token, uint256 _amount) internal;
function _withdrawTokens(address _token, uint256 _amount) internal;
function previewWithdraw(address _token, uint256 _amount) public view returns (uint256);
function interestAmount(address _token) public view returns (uint256);
}// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2021-2022 Dai Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity 0.4.24;
interface ISavingsDai {
function totalSupply() external view returns (uint256);
function balanceOf(address) external view returns (uint256);
function allowance(address, address) external view returns (uint256);
function approve(address, uint256) external returns (bool);
function transfer(address, uint256) external returns (bool);
function transferFrom(address, address, uint256) external returns (bool);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function version() external view returns (string memory);
function decimals() external view returns (uint8);
function deploymentChainId() external view returns (uint256);
function PERMIT_TYPEHASH() external view returns (bytes32);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function nonces(address) external view returns (uint256);
function vat() external view returns (address);
function daiJoin() external view returns (address);
function dai() external view returns (address);
function pot() external view returns (address);
function increaseAllowance(address, uint256) external returns (bool);
function decreaseAllowance(address, uint256) external returns (bool);
function asset() external view returns (address);
function totalAssets() external view returns (uint256);
function convertToShares(uint256) external view returns (uint256);
function convertToAssets(uint256) external view returns (uint256);
function maxDeposit(address) external view returns (uint256);
function previewDeposit(uint256) external view returns (uint256);
function deposit(uint256, address) external returns (uint256);
function deposit(uint256, address, uint16) external returns (uint256);
function maxMint(address) external view returns (uint256);
function previewMint(uint256) external view returns (uint256);
function mint(uint256, address) external returns (uint256);
function mint(uint256, address, uint16) external returns (uint256);
function maxWithdraw(address) external view returns (uint256);
function previewWithdraw(uint256) external view returns (uint256);
function withdraw(uint256, address, address) external returns (uint256);
function maxRedeem(address) external view returns (uint256);
function previewRedeem(uint256) external view returns (uint256);
function redeem(uint256, address, address) external returns (uint256);
function permit(address, address, uint256, uint256, bytes) external;
function permit(address, address, uint256, uint256, uint8, bytes32, bytes32) external;
}pragma solidity 0.4.24;
import "../upgradeability/EternalStorage.sol";
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import "./Validatable.sol";
import "../libraries/Message.sol";
import "./MessageRelay.sol";
import "./BasicBridge.sol";
import "./BasicTokenBridge.sol";
import "./MessageRelay.sol";
contract BasicForeignBridge is EternalStorage, Validatable, BasicBridge, BasicTokenBridge, MessageRelay {
/// triggered when relay of deposit from HomeBridge is complete
event RelayedMessage(address recipient, uint256 value, bytes32 transactionHash);
event UserRequestForAffirmation(address recipient, uint256 value, bytes32 nonce);
/**
* @dev Validates provided signatures and relays a given message
* @param message bytes to be relayed
* @param signatures bytes blob with signatures to be validated
*/
function executeSignatures(bytes message, bytes signatures) external {
Message.hasEnoughValidSignatures(message, signatures, validatorContract(), false);
address recipient;
uint256 amount;
bytes32 nonce;
address contractAddress;
address tokenAddress;
(recipient, amount, nonce, contractAddress, tokenAddress) = Message.parseMessage(message);
if (withinExecutionLimit(amount)) {
require(contractAddress == address(this));
require(!relayedMessages(nonce));
setRelayedMessages(nonce, true);
bytes32 hashMsg = keccak256(abi.encodePacked(recipient, amount, nonce));
if (HASHI_IS_ENABLED && HASHI_IS_MANDATORY) require(isApprovedByHashi(hashMsg));
require(onExecuteMessage(recipient, amount, nonce, tokenAddress));
emit RelayedMessage(recipient, amount, nonce);
} else {
onFailedMessage(recipient, amount, nonce);
}
}
function onMessage(
uint256, /*messageId*/
uint256 chainId,
address sender,
uint256 threshold,
address[] adapters,
bytes data
) external returns (bytes) {
_validateHashiMessage(chainId, threshold, sender, adapters);
bytes32 hashMsg = keccak256(data);
require(!isApprovedByHashi(hashMsg));
_setHashiApprovalForMessage(hashMsg, true);
}
function _emitUserRequestForAffirmationIncreaseNonceAndMaybeSendDataWithHashi(address _receiver, uint256 _amount)
internal
{
uint256 currentNonce = nonce();
setNonce(currentNonce + 1);
emit UserRequestForAffirmation(_receiver, _amount, bytes32(currentNonce));
_maybeSendDataWithHashi(abi.encodePacked(_receiver, _amount, bytes32(currentNonce)));
}
/**
* @dev Internal function for updating fallback gas price value.
* @param _gasPrice new value for the gas price, zero gas price is not allowed.
*/
function _setGasPrice(uint256 _gasPrice) internal {
require(_gasPrice > 0);
super._setGasPrice(_gasPrice);
}
/* solcov ignore next */
function onExecuteMessage(address, uint256, bytes32, address) internal returns (bool);
/* solcov ignore next */
function onFailedMessage(address, uint256, bytes32) internal;
}// SPDX-License-Identifier:MIT
// solhint-disable no-inline-assembly
pragma solidity 0.4.24;
import "./interfaces/IRelayRecipient.sol";
/**
* A base contract to be inherited by any contract that want to receive relayed transactions
* A subclass must use "_msgSender()" instead of "msg.sender"
*/
contract BaseRelayRecipient is IRelayRecipient {
/**
* return the sender of this call.
* if the call came through our trusted forwarder, return the original sender.
* otherwise, return `msg.sender`.
* should be used in the contract anywhere instead of msg.sender
*/
function _msgSender() internal view returns (address ret) {
if (msg.data.length >= 24 && isTrustedForwarder(msg.sender)) {
// At this point we know that the sender is a trusted forwarder,
// so we trust that the last bytes of msg.data are the verified sender address.
// extract sender address from the end of msg.data
assembly {
ret := shr(96, calldataload(sub(calldatasize, 20)))
}
} else {
return msg.sender;
}
}
/**
* return the msg.data of this call.
* if the call came through our trusted forwarder, then the real sender was appended as the last 20 bytes
* of the msg.data - so this method will strip those 20 bytes off.
* otherwise, return `msg.data`
* should be used in the contract instead of msg.data, where the difference matters (e.g. when explicitly
* signing or hashing the
*/
function _msgData() internal view returns (bytes memory ret) {
if (msg.data.length >= 24 && isTrustedForwarder(msg.sender)) {
// At this point we know that the sender is a trusted forwarder,
// we copy the msg.data , except the last 20 bytes (and update the total length)
assembly {
let ptr := mload(0x40)
// copy only size-20 bytes
let size := sub(calldatasize, 20)
// structure RLP data as <offset> <length> <bytes>
mstore(ptr, 0x20)
mstore(add(ptr, 32), size)
calldatacopy(add(ptr, 64), 0, size)
return(ptr, add(size, 64))
}
} else {
return msg.data;
}
}
}// SPDX-License-Identifier:MIT
pragma solidity 0.4.24;
interface IKnowForwarderAddress {
/**
* return the forwarder we trust to forward relayed transactions to us.
* the forwarder is required to verify the sender's signature, and verify
* the call is not a replay.
*/
function getTrustedForwarder() external view returns (address);
}pragma solidity ^0.4.24;
import "./ERC20Basic.sol";
/**
* @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
);
}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;
}
}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;
}pragma solidity 0.4.24;
import "../upgradeability/EternalStorage.sol";
import "../interfaces/IUpgradeabilityOwnerStorage.sol";
/**
* @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;
}
}pragma solidity 0.4.24;
interface IInterestReceiver {
function onInterestReceived(address _token) external;
}pragma solidity 0.4.24;
import "../interfaces/IBridgeValidators.sol";
import "../upgradeability/EternalStorage.sol";
import "./ValidatorStorage.sol";
contract Validatable is EternalStorage, ValidatorStorage {
function validatorContract() public view returns (IBridgeValidators) {
return IBridgeValidators(addressStorage[VALIDATOR_CONTRACT]);
}
function requiredSignatures() public view returns (uint256) {
return validatorContract().requiredSignatures();
}
function _onlyValidator() internal {
require(validatorContract().isValidator(msg.sender));
}
}pragma solidity 0.4.24;
import "../interfaces/IBridgeValidators.sol";
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
// offset 136: 20 bytes :: address - token address
// 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 nonce, address contractAddress, address tokenAddress)
{
require(isMessageValid(message));
assembly {
recipient := mload(add(message, 20))
amount := mload(add(message, 52))
nonce := mload(add(message, 84))
contractAddress := mload(add(message, 104))
tokenAddress := mload(add(message, 124))
}
if (message.length == 104) {
tokenAddress = 0x6B175474E89094C44Da98b954EedeAC495271d0F; // DAI address
}
}
///@dev original message length is 104. Message with 124 has appended token address.
function isMessageValid(bytes _msg) internal pure returns (bool) {
return _msg.length == 104 || _msg.length == 124;
}
function recoverAddressFromSignedMessage(bytes signature, bytes message, bool isAMBMessage)
internal
pure
returns (address)
{
require(isMessageValid(message));
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;
if (message.length == 104) {
msgLength = "104";
}else if(message.length == 124){
msgLength = "124";
}else{
revert();
}
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);
}
}pragma solidity 0.4.24;
import "../upgradeability/EternalStorage.sol";
contract MessageRelay is EternalStorage {
function relayedMessages(bytes32 _nonce) public view returns (bool) {
return boolStorage[keccak256(abi.encodePacked("relayedMessages", _nonce))];
}
function setRelayedMessages(bytes32 _nonce, bool _status) internal {
boolStorage[keccak256(abi.encodePacked("relayedMessages", _nonce))] = _status;
}
}pragma solidity 0.4.24;
import "./Upgradeable.sol";
import "./InitializableBridge.sol";
import "openzeppelin-solidity/contracts/AddressUtils.sol";
import "./Validatable.sol";
import "./Ownable.sol";
import "./Claimable.sol";
import "./VersionableBridge.sol";
import "./DecimalShiftBridge.sol";
import "../interfaces/hashi/IYaho.sol";
import "../interfaces/IHashiManager.sol";
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"))
bytes32 internal constant HASHI_MANAGER = 0x660d8ed18395a9aa930e304e0bb5e6e51957af1fa215b11db48bfda3dd38d511; // keccak256(abi.encodePacked("hashiManager"))
bool public constant HASHI_IS_ENABLED = true;
bool public constant HASHI_IS_MANDATORY = false;
function isApprovedByHashi(bytes32 hashMsg) public view returns (bool) {
return boolStorage[keccak256(abi.encodePacked("messagesApprovedByHashi", hashMsg))];
}
/**
* @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];
}
function hashiManager() public view returns (IHashiManager) {
return IHashiManager(addressStorage[HASHI_MANAGER]);
}
function setHashiManager(address _hashiManager) external onlyOwner {
addressStorage[HASHI_MANAGER] = _hashiManager;
}
/**
* @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);
}
function _setHashiApprovalForMessage(bytes32 hashMsg, bool status) internal {
boolStorage[keccak256(abi.encodePacked("messagesApprovedByHashi", hashMsg))] = status;
}
function resendDataWithHashi(bytes data) external {
require(boolStorage[keccak256(abi.encodePacked("dataSentWithHashi", data))]);
_dispatchMessageWithHashi(data);
}
function _maybeSendDataWithHashi(bytes data) internal {
if (HASHI_IS_ENABLED) {
boolStorage[keccak256(abi.encodePacked("dataSentWithHashi", data))] = true;
_dispatchMessageWithHashi(data);
}
}
function _dispatchMessageWithHashi(bytes data) internal {
IHashiManager manager = hashiManager();
IYaho(manager.yaho()).dispatchMessage(
manager.targetChainId(),
manager.threshold(),
manager.targetAddress(),
data,
manager.reporters(),
manager.adapters()
);
}
function _validateHashiMessage(uint256 chainId, uint256 threshold, address sender, address[] adapters) internal {
IHashiManager manager = hashiManager();
require(
HASHI_IS_ENABLED &&
msg.sender == manager.yaru() &&
chainId == manager.targetChainId() &&
sender == manager.targetAddress() &&
threshold == manager.expectedThreshold() &&
keccak256(abi.encodePacked(adapters)) == manager.expectedAdaptersHash()
);
}
}pragma solidity 0.4.24;
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "../upgradeability/EternalStorage.sol";
import "./DecimalShiftBridge.sol";
import "./Ownable.sol";
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"))
bytes32 internal constant TOKEN_BRIDGE_NONCE = 0x8fe4c9f18420598a0f0a5c996b969714f39cc770f1900e60d2697139e137749b; // keccak256(abi.encodePacked("tokenBridgeNonce"))
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) {
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]);
}
function nonce() public view returns (uint256) {
return uintStorage[TOKEN_BRIDGE_NONCE];
}
function setNonce(uint256 nonce) internal {
uintStorage[TOKEN_BRIDGE_NONCE] = nonce;
}
}// SPDX-License-Identifier:MIT
pragma solidity 0.4.24;
/**
* a contract must implement this interface in order to support relayed transaction.
* It is better to inherit the BaseRelayRecipient as its implementation.
*/
contract IRelayRecipient {
/**
* return if the forwarder is trusted to forward relayed transactions to us.
* the forwarder is required to verify the sender's signature, and verify
* the call is not a replay.
*/
function isTrustedForwarder(address forwarder) public view returns (bool);
/**
* return the sender of this call.
* if the call came through our trusted forwarder, then the real sender is appended as the last 20 bytes
* of the msg.data.
* otherwise, return `msg.sender`
* should be used in the contract anywhere instead of msg.sender
*/
function _msgSender() internal view returns (address);
/**
* return the msg.data of this call.
* if the call came through our trusted forwarder, then the real sender was appended as the last 20 bytes
* of the msg.data - so this method will strip those 20 bytes off.
* otherwise, return `msg.data`
* should be used in the contract instead of msg.data, where the difference matters (e.g. when explicitly
* signing or hashing the
*/
function _msgData() internal view returns (bytes memory);
function versionRecipient() external view returns (string memory);
}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);
}pragma solidity 0.4.24;
interface IUpgradeabilityOwnerStorage {
function upgradeabilityOwner() external view returns (address);
}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);
function addValidator(address _validator) external;
function removeValidator(address _validator) external;
function setRequiredSignatures(uint256 _requiredSignatures) external;
}pragma solidity 0.4.24;
contract ValidatorStorage {
bytes32 internal constant VALIDATOR_CONTRACT = 0x5a74bb7e202fb8e4bf311841c7d64ec19df195fee77d7e7ae749b27921b6ddfe; // keccak256(abi.encodePacked("validatorContract"))
}pragma solidity 0.4.24;
import "../interfaces/IUpgradeabilityOwnerStorage.sol";
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 */
_;
}
}pragma solidity 0.4.24;
import "./Initializable.sol";
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];
}
}pragma solidity 0.4.24;
import "../libraries/Address.sol";
import "../libraries/SafeERC20.sol";
/**
* @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);
}
}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);
}pragma solidity 0.4.24;
import "../upgradeability/EternalStorage.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
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));
}
}pragma solidity 0.4.24;
interface IYaho {
function dispatchMessage(
uint256 targetChainId,
uint256 threshold,
address receiver,
bytes data,
address[] reporters,
address[] adapters
) external returns (uint256);
}pragma solidity 0.4.24;
interface IHashiManager {
function adapters() external view returns (address[]);
function reporters() external view returns (address[]);
function expectedAdaptersHash() external view returns (bytes32);
function expectedThreshold() external view returns (uint256);
function yaho() external view returns (address);
function yaru() external view returns (address);
function targetAddress() external view returns (address);
function targetChainId() external view returns (uint256);
function threshold() external view returns (uint256);
}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;
}
}pragma solidity 0.4.24;
import "../upgradeability/EternalStorage.sol";
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];
}
}pragma solidity 0.4.24;
import "../upgradeable_contracts/Sacrifice.sol";
/**
* @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);
}
}
}pragma solidity 0.4.24;
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "../interfaces/ERC677.sol";
/**
* @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)
}
}
}
}
}pragma solidity 0.4.24;
contract Sacrifice {
constructor(address _recipient) public payable {
selfdestruct(_recipient);
}
}pragma solidity 0.4.24;
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
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);
}{
"remappings": [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"openzeppelin-solidity/=node_modules/openzeppelin-solidity/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 10
},
"metadata": {
"useLiteralContent": false
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "constantinople"
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"constant":false,"inputs":[{"name":"_receiver","type":"address"},{"name":"_amount","type":"uint256"}],"name":"relayTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"invest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"refillBridge","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_amount","type":"uint256"}],"name":"payInterest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"erc20token","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"HASHI_IS_MANDATORY","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"message","type":"bytes"},{"name":"signatures","type":"bytes"},{"name":"maxTokensFee","type":"uint256"}],"name":"executeSignaturesGSN","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nonce","type":"bytes32"}],"name":"relayedMessages","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_day","type":"uint256"}],"name":"totalSpentPerDay","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"sDaiToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"isInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_dailyLimit","type":"uint256"}],"name":"setExecutionDailyLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentDay","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"requiredBlockConfirmations","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"message","type":"bytes"},{"name":"signatures","type":"bytes"}],"name":"executeSignatures","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBridgeMode","outputs":[{"name":"_data","type":"bytes4"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"executionDailyLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_token","type":"address"}],"name":"minInterestPaid","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"versionRecipient","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_day","type":"uint256"}],"name":"totalExecutedPerDay","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_token","type":"address"}],"name":"minCashThreshold","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"dailyLimit","outputs":[{"name":"","type":"uint256"}],"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":false,"inputs":[{"name":"_validatorContract","type":"address"},{"name":"_erc20token","type":"address"},{"name":"_requiredBlockConfirmations","type":"uint256"},{"name":"_gasPrice","type":"uint256"},{"name":"_dailyLimitMaxPerTxMinPerTxArray","type":"uint256[3]"},{"name":"_homeDailyLimitHomeMaxPerTxArray","type":"uint256[2]"},{"name":"_owner","type":"address"},{"name":"_decimalShift","type":"int256"},{"name":"_bridgeOnOtherSide","type":"address"}],"name":"initialize","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"investDai","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"data","type":"bytes"}],"name":"resendDataWithHashi","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"hashiManager","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_paymaster","type":"address"}],"name":"setPayMaster","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_amount","type":"uint256"}],"name":"withinExecutionLimit","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"executionMaxPerTx","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"HASHI_IS_ENABLED","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","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":"hashMsg","type":"bytes32"}],"name":"isApprovedByHashi","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_receiver","type":"address"}],"name":"setInterestReceiver","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"maxAvailablePerTx","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","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":false,"inputs":[{"name":"_minPerTx","type":"uint256"}],"name":"setMinPerTx","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_minInterestPaid","type":"uint256"}],"name":"setMinInterestPaid","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_minCashThreshold","type":"uint256"}],"name":"setMinCashThreshold","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_token","type":"address"}],"name":"interestReceiver","outputs":[{"name":"","type":"address"}],"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":"nonce","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_dailyLimit","type":"uint256"}],"name":"setDailyLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_token","type":"address"},{"name":"_amount","type":"uint256"}],"name":"previewWithdraw","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"daiToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"_hashiManager","type":"address"}],"name":"setHashiManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_gasPrice","type":"uint256"}],"name":"setGasPrice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"recoverAmount","type":"uint256"}],"name":"recoverLegacyTransfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_maxPerTx","type":"uint256"}],"name":"setMaxPerTx","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_token","type":"address"}],"name":"interestAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"USDS","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_minCashThreshold","type":"uint256"},{"name":"_minInterestPaid","type":"uint256"},{"name":"_interestReceiver","type":"address"}],"name":"initializeInterest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTrustedForwarder","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_token","type":"address"}],"name":"investedAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_token","type":"address"}],"name":"isInterestEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"","type":"uint256"},{"name":"chainId","type":"uint256"},{"name":"sender","type":"address"},{"name":"threshold","type":"uint256"},{"name":"adapters","type":"address[]"},{"name":"data","type":"bytes"}],"name":"onMessage","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_trustedForwarder","type":"address"}],"name":"setTrustedForwarder","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimalShift","outputs":[{"name":"","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minPerTx","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DAI","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_amount","type":"uint256"}],"name":"withinLimit","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DAI_USDS","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_maxPerTx","type":"uint256"}],"name":"setExecutionMaxPerTx","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"disableInterest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"maxPerTx","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"swapSDAIToUSDS","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"gasPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"PaidInterest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"recipient","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"transactionHash","type":"bytes32"}],"name":"RelayedMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"recipient","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"nonce","type":"bytes32"}],"name":"UserRequestForAffirmation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newLimit","type":"uint256"}],"name":"DailyLimitChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newLimit","type":"uint256"}],"name":"ExecutionDailyLimitChanged","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"}]Contract Creation Code
608060405234801561001057600080fd5b50615e6e80620000216000396000f3006080604052600436106103315760003560e01c63ffffffff16806301e4f53a1461033657806303f9c7931461035c5780630fd6d5281461037d5780631b7623be146103925780631dcea427146103b65780631ded8468146103e75780631e86b2911461041057806321d800ec1461043f5780632bd0bb05146104575780633853b7a114610481578063392e53cd146104965780633dd95d1b146104ab5780633e6968b6146104c35780633f0a9f65146104d85780633f7658fd146104ed578063437764df1461051957806343b37dd31461054b5780634774f56314610560578063486ff0cd146105815780634fb3fef71461060b5780635726ff3014610623578063572b6c051461064457806367eeba0c1461066557806369ffa08a1461067a5780636da8b996146106a157806374948c52146106e9578063785b15d5146106fe5780637ea5f8d41461071e57806384fe8ab214610733578063879ce676146107545780638aa1949a1461076c5780638b94e255146107815780638d068043146107965780638da5cb5b146107ab5780638dc8cf87146107c0578063904377ec146107d857806395e54a17146107ff57806399439089146108145780639a454b99146108295780639cb7595a1461083e578063a2a6ca271461087f578063a36b85fd14610897578063a4b4b233146108bb578063a83bb236146108df578063acf5c68914610900578063affed0e014610918578063b20d30a91461092d578063bbc6f1dc14610945578063be22f546146103b6578063bec9fa7c14610969578063bf1fe4201461098a578063c2a2872d146109a2578063c6f6f216146109c6578063c779c1c3146109de578063c8ef95ae146109ff578063cd0fc03314610a14578063ce1b815f14610a43578063cff7744414610a58578063d2ef866014610a79578063d496af2414610a9a578063da74222814610adf578063dae5f0fd14610b00578063df25f3f014610b15578063e0bab4c414610b2a578063ea9f496814610b3f578063ecd9217914610b57578063f20151e114610b6c578063f2fde38b14610b84578063f50dace614610ba5578063f968adbe14610bc6578063fda8babc14610bdb578063fe173b9714610bf0575b600080fd5b34801561034257600080fd5b5061035a600160a060020a0360043516602435610c05565b005b34801561036857600080fd5b5061035a600160a060020a0360043516610e8f565b34801561038957600080fd5b5061035a610f88565b34801561039e57600080fd5b5061035a600160a060020a0360043516602435611094565b3480156103c257600080fd5b506103cb611243565b60408051600160a060020a039092168252519081900360200190f35b3480156103f357600080fd5b506103fc611255565b604080519115158252519081900360200190f35b34801561041c57600080fd5b5061035a602460048035828101929082013591813591820191013560443561125a565b34801561044b57600080fd5b506103fc60043561144a565b34801561046357600080fd5b5061046f600435611508565b60408051918252519081900360200190f35b34801561048d57600080fd5b506103cb6115bb565b3480156104a257600080fd5b506103fc6115cd565b3480156104b757600080fd5b5061035a6004356115fa565b3480156104cf57600080fd5b5061046f611684565b3480156104e457600080fd5b5061046f61168d565b3480156104f957600080fd5b5061035a60246004803582810192908201359181359182019101356116b7565b34801561052557600080fd5b5061052e6118b1565b60408051600160e060020a03199092168252519081900360200190f35b34801561055757600080fd5b5061046f6118bf565b34801561056c57600080fd5b5061046f600160a060020a03600435166118e9565b34801561058d57600080fd5b5061059661196e565b6040805160208082528351818301528351919283929083019185019080838360005b838110156105d05781810151838201526020016105b8565b50505050905090810190601f1680156105fd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561061757600080fd5b5061046f600435611990565b34801561062f57600080fd5b5061046f600160a060020a0360043516611a04565b34801561065057600080fd5b506103fc600160a060020a0360043516611a8a565b34801561067157600080fd5b5061046f611ac2565b34801561068657600080fd5b5061035a600160a060020a0360043581169060243516611aec565b3480156106ad57600080fd5b506103fc600160a060020a03600435811690602435811690604435906064359060849060e4906101243581169061014435906101643516611c66565b3480156106f557600080fd5b5061035a611ebc565b34801561070a57600080fd5b5061035a6004803560248101910135611ed5565b34801561072a57600080fd5b506103cb611fd2565b34801561073f57600080fd5b5061035a600160a060020a0360043516612005565b34801561076057600080fd5b506103fc600435612067565b34801561077857600080fd5b5061046f6120a5565b34801561078d57600080fd5b506103fc6120cf565b3480156107a257600080fd5b5061046f6120d4565b3480156107b757600080fd5b506103cb612149565b3480156107cc57600080fd5b506103fc60043561217c565b3480156107e457600080fd5b5061035a600160a060020a03600435811690602435166121fd565b34801561080b57600080fd5b5061046f612223565b34801561082057600080fd5b506103cb61227d565b34801561083557600080fd5b5061046f6122c2565b34801561084a57600080fd5b506108536122ec565b6040805167ffffffffffffffff9485168152928416602084015292168183015290519081900360600190f35b34801561088b57600080fd5b5061035a6004356122f7565b3480156108a357600080fd5b5061035a600160a060020a036004351660243561236f565b3480156108c757600080fd5b5061035a600160a060020a0360043516602435612395565b3480156108eb57600080fd5b506103cb600160a060020a03600435166123bb565b34801561090c57600080fd5b5061035a60043561248d565b34801561092457600080fd5b5061046f6124b5565b34801561093957600080fd5b5061035a6004356124df565b34801561095157600080fd5b5061046f600160a060020a0360043516602435612569565b34801561097557600080fd5b5061035a600160a060020a036004351661264e565b34801561099657600080fd5b5061035a6004356126b0565b3480156109ae57600080fd5b5061035a600160a060020a03600435166024356126d5565b3480156109d257600080fd5b5061035a6004356128ff565b3480156109ea57600080fd5b5061046f600160a060020a0360043516612973565b348015610a0b57600080fd5b506103cb612a80565b348015610a2057600080fd5b5061035a600160a060020a03600435811690602435906044359060643516612a92565b348015610a4f57600080fd5b506103cb612b8d565b348015610a6457600080fd5b5061046f600160a060020a0360043516612bc0565b348015610a8557600080fd5b506103fc600160a060020a0360043516612c44565b348015610aa657600080fd5b5061059660048035906024803591600160a060020a0360443516916064359160843580830192908201359160a435918201910135612cca565b348015610aeb57600080fd5b5061035a600160a060020a0360043516612d51565b348015610b0c57600080fd5b5061046f612db3565b348015610b2157600080fd5b5061046f612e01565b348015610b3657600080fd5b506103cb612e2b565b348015610b4b57600080fd5b506103fc600435612e3d565b348015610b6357600080fd5b506103cb612e88565b348015610b7857600080fd5b5061035a600435612e9a565b348015610b9057600080fd5b5061035a600160a060020a0360043516612ef2565b348015610bb157600080fd5b5061035a600160a060020a0360043516612f17565b348015610bd257600080fd5b5061046f612f4a565b348015610be757600080fd5b5061035a612f74565b348015610bfc57600080fd5b5061046f61331c565b610c0d613346565b600160a060020a0383811691161415610c70576040805160e560020a62461bcd02815260206004820152601960248201527f52656c6179656420746f20427269646765206164647265737300000000000000604482015290519081900360640190fd5b600160a060020a0382161515610cd0576040805160e560020a62461bcd02815260206004820152601760248201527f52656c6179656420746f204e756c6c2061646472657373000000000000000000604482015290519081900360640190fd5b600160a060020a038216301415610d31576040805160e560020a62461bcd02815260206004820152601760248201527f52656c6179656420746f20746869732061646472657373000000000000000000604482015290519081900360640190fd5b60008111610d81576040805160e560020a62461bcd0281526020600482015260126024820152607060020a7152656c61796564207a65726f2066756e647302604482015290519081900360640190fd5b610d8a81612e3d565b1515610de0576040805160e560020a62461bcd02815260206004820152601a60248201527f4578636565647320627269646765206461696c79206c696d6974000000000000604482015290519081900360640190fd5b610df1610deb611684565b82613379565b610df9611243565b6040805160e060020a6323b872dd028152336004820152306024820152604481018490529051600160a060020a0392909216916323b872dd916064808201926020929091908290030181600087803b158015610e5457600080fd5b505af1158015610e68573d6000803e3d6000fd5b505050506040513d6020811015610e7e57600080fd5b50610e8b90508282613438565b5050565b600080600083610e9e81612c44565b1515610eee576040805160e560020a62461bcd0281526020600482015260146024820152606260020a73125b9d195c995cdd081b9bdd08115b98589b195902604482015290519081900360640190fd5b610ef7856134e2565b9350610f0285611a04565b9250828411610f50576040805160e560020a62461bcd02815260206004820152600f6024820152608860020a6e42616c616e636520746f6f204c6f7702604482015290519081900360640190fd5b8284039150610f7785610f7284610f6689612bc0565b9063ffffffff61356216565b613575565b610f8185836135f8565b5050505050565b6040805160e060020a6370a08231028152306004820152905160009182918291600080516020615dc3833981519152916370a082319160248082019260209290919082900301818787803b158015610fdf57600080fd5b505af1158015610ff3573d6000803e3d6000fd5b505050506040513d602081101561100957600080fd5b50519250611024600080516020615dc3833981519152611a04565b9150818310611073576040805160e560020a62461bcd0281526020600482015260106024820152608260020a6f109c9a5919d9481a5cc8119a5b1b195902604482015290519081900360640190fd5b5081810361108f600080516020615dc3833981519152826137b7565b505050565b6000806000846110a381612c44565b15156110f3576040805160e560020a62461bcd0281526020600482015260146024820152606260020a73125b9d195c995cdd081b9bdd08115b98589b195902604482015290519081900360640190fd5b6110fb611243565b600160a060020a03878116911614611153576040805160e560020a62461bcd0281526020600482015260106024820152608160020a6f2737ba10313934b233b2902a37b5b2b702604482015290519081900360640190fd5b61115c86612973565b935083851061116b578361116d565b845b9250611178866118e9565b8310156111cf576040805160e560020a62461bcd02815260206004820152601c60248201527f436f6c6c65637461626c6520696e74657265737420746f6f206c6f7700000000604482015290519081900360640190fd5b6111e086610f7285610f668a612bc0565b6111e9866123bb565b91506111f5828461380a565b60408051600160a060020a038481168252602082018690528251908916927f222348fe8b30f078a8a4da2f55f16d24d70bc40d3ec49d295d7ad1d11e666887928290030190a2505050505050565b600080516020615dc383398151915290565b600081565b600080600080600061126b33611a8a565b15156112b8576040805160e560020a62461bcd0281526020600482015260116024820152607960020a7034b73b30b634b2103337b93bb0b93232b902604482015290519081900360640190fd5b61132f8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505089898080601f01602080910402602001604051908101604052809392919081815260200183838082843750611328945061227d9350505050565b6000613977565b6113688a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843750613bfb945050505050565b93985091965094509250905061137c611243565b600160a060020a0382811691161461139357600080fd5b61139c84612067565b1561143357838611156113ae57600080fd5b600160a060020a03821630146113c357600080fd5b6113cc8361144a565b156113d657600080fd5b6113e1836001613c5e565b6113ec858588613d25565b15156113f757600080fd5b60408051600160a060020a0387168152602081018690528082018590529051600080516020615be38339815191529181900360600190a161143e565b61143e858585610331565b50505050505050505050565b600060046000836040516020018080608860020a6e72656c617965644d6573736167657302815250600f0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106114c45780518252601f1990920191602091820191016114a5565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1695945050505050565b6000806000836040516020018080608060020a6f746f74616c5370656e74506572446179028152506010018281526020019150506040516020818303038152906040526040518082805190602001908083835b6020831061157a5780518252601f19909201916020918201910161155b565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205495945050505050565b6000805160206159e383398151915290565b600080516020615d038339815191526000526004602052600080516020615b638339815191525460ff1690565b611602612149565b600160a060020a0316331461161657600080fd5b61161e6120a5565b811180611629575080155b151561163457600080fd5b600080516020615a4383398151915260009081526020908152600080516020615ca3833981519152829055604080518381529051600080516020615983833981519152929181900390910190a150565b62015180420490565b600080516020615c238339815191526000908152602052600080516020615c838339815191525490565b6000806000806000806117308a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505089898080601f01602080910402602001604051908101604052809392919081815260200183838082843750611328945061227d9350505050565b6117698a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843750613bfb945050505050565b93995091975095509350915061177e85612067565b156118a657600160a060020a038316301461179857600080fd5b6117a18461144a565b156117ab57600080fd5b6117b6846001613c5e565b60408051600160a060020a03881660601b60208083019190915260348201889052605480830188905283518084039091018152607490920192839052815191929182918401908083835b6020831061181f5780518252601f199092019160209182019101611800565b5181516020939093036101000a60001901801990911692169190911790526040519201829003909120935061185392505050565b61185f86868685613d4a565b151561186a57600080fd5b60408051600160a060020a0388168152602081018790528082018690529051600080516020615be38339815191529181900360600190a161143e565b61143e868686610331565b60e160020a630c3b16a30290565b600080516020615a438339815191526000908152602052600080516020615ca38339815191525490565b6000806000836040516020018080608a60020a6e1b5a5b925b9d195c995cdd14185a5902815250600f0182600160a060020a0316600160a060020a031660601b81526014019150506040516020818303038152906040526040518082805190602001908083836020831061157a5780518252601f19909201916020918201910161155b565b604080518082019091526005815260d860020a64312e302e3102602082015290565b6000806000836040516020018080606860020a72746f74616c4578656375746564506572446179028152506013018281526020019150506040516020818303038152906040526040518082805190602001908083836020831061157a5780518252601f19909201916020918201910161155b565b6000806000836040516020018080608260020a6f1b5a5b90d85cda151a1c995cda1bdb190281525060100182600160a060020a0316600160a060020a031660601b81526014019150506040516020818303038152906040526040518082805190602001908083836020831061157a5780518252601f19909201916020918201910161155b565b600080516020615a038339815191526000526002602052600080516020615ba383398151915254600160a060020a0390811691161490565b600080516020615b438339815191526000908152602052600080516020615e238339815191525490565b60008030600160a060020a0316636fde82026040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b2a57600080fd5b505af1158015611b3e573d6000803e3d6000fd5b505050506040513d6020811015611b5457600080fd5b5051600160a060020a03163314611b6a57600080fd5b50600080516020615dc383398151915290506000805160206159e3833981519152600160a060020a038416821415611be2576040805160e560020a62461bcd0281526020600482015260106024820152608060020a6f43616e277420636c61696d205553445302604482015290519081900360640190fd5b80600160a060020a031684600160a060020a0316141580611c095750611c0782612c44565b155b1515611c56576040805160e560020a62461bcd0281526020600482015260116024820152607860020a7043616e277420636c61696d20735553445302604482015290519081900360640190fd5b611c608484613fac565b50505050565b6040805160048152602481018252602081018051600160e060020a031660e160020a6337ef4101021781529151815160009330939291829190808383895b83811015611cbc578181015183820152602001611ca4565b50505050905090810190601f168015611ce95780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af19150501580611d78575030600160a060020a0316636fde82026040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611d4057600080fd5b505af1158015611d54573d6000803e3d6000fd5b505050506040513d6020811015611d6a57600080fd5b5051600160a060020a031633145b80611d8257503330145b1515611d8d57600080fd5b611d956115cd565b15611d9f57600080fd5b611da88a613fea565b1515611db357600080fd5b611dbb611243565b600160a060020a038a8116911614611dd257600080fd5b8215611ddd57600080fd5b600080516020615b238339815191528054600160a060020a031916600160a060020a038c16179055600080516020615963833981519152600090815260205243600080516020615b0383398151915255611e3688613ff2565b611e3f87614061565b604080516060818101909252611e679188906003908390839080828437506140779350505050565b604080518082018252611e8c9187906002908390839080828437506141569350505050565b611e95846141d1565b611e9e82614277565b611ea66142d2565b611eae6115cd565b9a9950505050505050505050565b611ed3600080516020615dc3833981519152610e8f565b565b6004600083836040516020018080607860020a706461746153656e74576974684861736869028152506011018383808284378201915050925050506040516020818303038152906040526040518082805190602001908083835b60208310611f4e5780518252601f199092019160209182019101611f2f565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1615159250611f9991505057600080fd5b610e8b82828080601f01602080910402602001604051908101604052809392919081815260200183838082843750614305945050505050565b600080516020615b838339815191526000526002602052600080516020615a6383398151915254600160a060020a031690565b61200d612149565b600160a060020a0316331461202157600080fd5b600080516020615ae38339815191526000526002602052600080516020615de38339815191528054600160a060020a031916600160a060020a0392909216919091179055565b60008061207e83610f66612079611684565b611990565b9050806120896118bf565b1015801561209e575061209a6120a5565b8311155b9392505050565b600080516020615e0383398151915260009081526020526000805160206159a38339815191525490565b600181565b60006120de61227d565b600160a060020a0316638d0680436040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561211857600080fd5b505af115801561212c573d6000803e3d6000fd5b505050506040513d602081101561214257600080fd5b5051905090565b600080516020615c638339815191526000526002602052600080516020615c4383398151915254600160a060020a031690565b600060046000836040516020018080604860020a766d65737361676573417070726f76656442794861736869028152506017018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106114c45780518252601f1990920191602091820191016114a5565b612205612149565b600160a060020a0316331461221957600080fd5b610e8b82826147d7565b6000806000806000612233612f4a565b935061223d611ac2565b925061224f61224a611684565b611508565b915081831161225f576000612263565b8183035b90508084106122725780612274565b835b94505050505090565b7f5a74bb7e202fb8e4bf311841c7d64ec19df195fee77d7e7ae749b27921b6ddfe6000526002602052600080516020615b2383398151915254600160a060020a031690565b6000805160206159638339815191526000908152602052600080516020615b038339815191525490565b600660016000909192565b6122ff612149565b600160a060020a0316331461231357600080fd5b6000811180156123295750612326611ac2565b81105b801561233b5750612338612f4a565b81105b151561234657600080fd5b600080516020615a838339815191526000908152602052600080516020615d2383398151915255565b612377612149565b600160a060020a0316331461238b57600080fd5b610e8b828261490a565b61239d612149565b600160a060020a031633146123b157600080fd5b610e8b828261498e565b600060026000836040516020018080608160020a6f34b73a32b932b9ba2932b1b2b4bb32b90281525060100182600160a060020a0316600160a060020a031660601b81526014019150506040516020818303038152906040526040518082805190602001908083835b602083106124435780518252601f199092019160209182019101612424565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a031695945050505050565b612495612149565b600160a060020a031633146124a957600080fd5b6124b281613ff2565b50565b600080516020615bc38339815191526000908152602052600080516020615ac38339815191525490565b6124e7612149565b600160a060020a031633146124fb57600080fd5b612503612f4a565b81118061250e575080155b151561251957600080fd5b600080516020615b4383398151915260009081526020908152600080516020615e23833981519152829055604080518381529051600080516020615d83833981519152929181900390910190a150565b6000600080516020615dc3833981519152600160a060020a038416146125c7576040805160e560020a62461bcd028152602060048201526008602482015260c060020a676e6f74205553445302604482015290519081900360640190fd5b6000805160206159e3833981519152600160a060020a0316630a28a477836040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561261b57600080fd5b505af115801561262f573d6000803e3d6000fd5b505050506040513d602081101561264557600080fd5b50519392505050565b612656612149565b600160a060020a0316331461266a57600080fd5b600080516020615b838339815191526000526002602052600080516020615a638339815191528054600160a060020a031916600160a060020a0392909216919091179055565b6126b8612149565b600160a060020a031633146126cc57600080fd5b6124b281614061565b600080600030600160a060020a0316636fde82026040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561271557600080fd5b505af1158015612729573d6000803e3d6000fd5b505050506040513d602081101561273f57600080fd5b5051600160a060020a0316331461275557600080fd5b6040805160e060020a6370a082310281523060048201529051600080516020615dc3833981519152916370a082319160248083019260209291908290030181600087803b1580156127a557600080fd5b505af11580156127b9573d6000803e3d6000fd5b505050506040513d60208110156127cf57600080fd5b505192506127ea600080516020615dc3833981519152611a04565b9150828410612843576040805160e560020a62461bcd02815260206004820152601860248201527f696e76616c69642077697468647261772062616c616e63650000000000000000604482015290519081900360640190fd5b81848403101561286c578284830103905061286c600080516020615dc3833981519152826137b7565b6040805160e060020a63a9059cbb028152600160a060020a0387166004820152602481018690529051600080516020615dc38339815191529163a9059cbb9160448083019260209291908290030181600087803b1580156128cc57600080fd5b505af11580156128e0573d6000803e3d6000fd5b505050506040513d60208110156128f657600080fd5b50505050505050565b612907612149565b600160a060020a0316331461291b57600080fd5b80158061293f575061292b612e01565b8111801561293f575061293c611ac2565b81105b151561294a57600080fd5b6000805160206159c38339815191526000908152602052600080516020615ce383398151915255565b60008080600080516020615dc3833981519152600160a060020a038516146129d3576040805160e560020a62461bcd028152602060048201526008602482015260c060020a674e6f74205553445302604482015290519081900360640190fd5b6040805160e060020a63ce96cb7702815230600482015290516000805160206159e38339815191529163ce96cb779160248083019260209291908290030181600087803b158015612a2357600080fd5b505af1158015612a37573d6000803e3d6000fd5b505050506040513d6020811015612a4d57600080fd5b50519150612a5a84612bc0565b670de0b6b3a7640000019050808211612a74576000612a78565b8082035b949350505050565b600080516020615dc383398151915281565b612a9a612149565b600160a060020a03163314612aae57600080fd5b612ab784614a13565b1515612b06576040805160e560020a62461bcd0281526020600482015260136024820152606a60020a72151bdad95b881b9bdd081cdd5c1c1bdc9d195902604482015290519081900360640190fd5b612b0f84612c44565b15612b64576040805160e560020a62461bcd02815260206004820152601860248201527f496e74657265737420616c726561647920656e61626c65640000000000000000604482015290519081900360640190fd5b612b6f846001614a2f565b612b79848461498e565b612b83848361490a565b611c6084826147d7565b600080516020615a038339815191526000526002602052600080516020615ba383398151915254600160a060020a031690565b6000806000836040516020018080609260020a6d1a5b9d995cdd1959105b5bdd5b9d02815250600e0182600160a060020a0316600160a060020a031660601b81526014019150506040516020818303038152906040526040518082805190602001908083836020831061157a5780518252601f19909201916020918201910161155b565b600060046000836040516020018080608a60020a6e1a5b9d195c995cdd115b98589b195902815250600f0182600160a060020a0316600160a060020a031660601b8152601401915050604051602081830303815290604052604051808280519060200190808383602083106114c45780518252601f1990920191602091820191016114a5565b60606000612d0789888a89898080602002602001604051908101604052809392919081815260200183836020028082843750614ab4945050505050565b83836040518083838082843782019150509250505060405180910390209050612d2f8161217c565b15612d3957600080fd5b612d44816001614db7565b5098975050505050505050565b612d59612149565b600160a060020a03163314612d6d57600080fd5b600080516020615a038339815191526000526002602052600080516020615ba38339815191528054600160a060020a031916600160a060020a0392909216919091179055565b7f1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee560009081526020527fd5c78dd9468716ca9bb96be25d56436811b20aab3523a9904b12deef1cab239d5490565b600080516020615a838339815191526000908152602052600080516020615d238339815191525490565b600080516020615aa383398151915281565b600080612e4f83610f6661224a611684565b905080612e5a611ac2565b10158015612e6f5750612e6b612f4a565b8311155b801561209e5750612e7e612e01565b9092101592915050565b600080516020615d4383398151915281565b612ea2612149565b600160a060020a03163314612eb657600080fd5b612ebe6118bf565b8110612ec957600080fd5b600080516020615e0383398151915260009081526020526000805160206159a383398151915255565b612efa612149565b600160a060020a03163314612f0e57600080fd5b6124b2816141d1565b612f1f612149565b600160a060020a03163314612f3357600080fd5b612f3f816000196137b7565b6124b2816000614a2f565b6000805160206159c38339815191526000908152602052600080516020615ce38339815191525490565b60408051606860020a72757067726164655f4441495f746f5f55534453028152815190819003601301902060008181526004602052918220549091908190819060ff161561300c576040805160e560020a62461bcd02815260206004820152601d60248201527f5553445320627269646765207567707261646520636f6d706c65746564000000604482015290519081900360640190fd5b6040805160e060020a63ce96cb7702815230600482015290517383f20f44975d03b1b09e64809b757c47f942beea9450849163ce96cb779160248083019260209291908290030181600087803b15801561306557600080fd5b505af1158015613079573d6000803e3d6000fd5b505050506040513d602081101561308f57600080fd5b50516040805160e260020a632d182be502815260048101839052306024820181905260448201529051919350600160a060020a0385169163b460af94916064808201926020929091908290030181600087803b1580156130ee57600080fd5b505af1158015613102573d6000803e3d6000fd5b505050506040513d602081101561311857600080fd5b506131349050600080516020615aa38339815191526000613575565b61314d600080516020615aa38339815191526000614a2f565b613166600080516020615aa3833981519152600061498e565b61317f600080516020615aa3833981519152600061490a565b6040805160e060020a6370a082310281523060048201529051600080516020615aa3833981519152916370a082319160248083019260209291908290030181600087803b1580156131cf57600080fd5b505af11580156131e3573d6000803e3d6000fd5b505050506040513d60208110156131f957600080fd5b50516040805160e060020a63095ea7b3028152600080516020615d438339815191526004820152602481018390529051919250600080516020615aa38339815191529163095ea7b3916044808201926020929091908290030181600087803b15801561326457600080fd5b505af1158015613278573d6000803e3d6000fd5b505050506040513d602081101561328e57600080fd5b50506040805160e160020a6379603d57028152306004820152602481018390529051600080516020615d438339815191529163f2c07aae91604480830192600092919082900301818387803b1580156132e657600080fd5b505af11580156132fa573d6000803e3d6000fd5b505050600094855250506004602052505060409020805460ff19166001179055565b600080516020615c038339815191526000908152602052600080516020615cc38339815191525490565b600080516020615a238339815191526000526002602052600080516020615d6383398151915254600160a060020a031690565b61338681610f6684611508565b600080846040516020018080608060020a6f746f74616c5370656e74506572446179028152506010018281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106133f65780518252601f1990920191602091820191016133d7565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020939093555050505050565b60006134426124b5565b905061345081600101614e37565b60408051600160a060020a038516815260208101849052600083901b8183015290517ff6968e689b3d8c24f22c10c2a3256bb5ca483a474e11bac08423baa049e38ae89181900360600190a160408051600160a060020a03851660601b602082015260348101849052600083901b60548083019190915282518083039091018152607490910190915261108f90614e60565b6040805160e060020a6370a082310281523060048201529051600091600160a060020a038416916370a082319160248082019260209290919082900301818787803b15801561353057600080fd5b505af1158015613544573d6000803e3d6000fd5b505050506040513d602081101561355a57600080fd5b505192915050565b8181018281101561356f57fe5b92915050565b80600080846040516020018080609260020a6d1a5b9d995cdd1959105b5bdd5b9d02815250600e0182600160a060020a0316600160a060020a031660601b8152601401915050604051602081830303815290604052604051808280519060200190808383602083106133f65780518252601f1990920191602091820191016133d7565b600080516020615dc3833981519152600160a060020a03831614613654576040805160e560020a62461bcd028152602060048201526008602482015260c060020a676e6f74205553445302604482015290519081900360640190fd5b6040805160e060020a63095ea7b30281526000805160206159e38339815191526004820152602481018390529051600080516020615dc38339815191529163095ea7b39160448083019260209291908290030181600087803b1580156136b957600080fd5b505af11580156136cd573d6000803e3d6000fd5b505050506040513d60208110156136e357600080fd5b50506040805160e060020a636e553f650281526004810183905230602482015290516000916000805160206159e383398151915291636e553f659160448082019260209290919082900301818787803b15801561373f57600080fd5b505af1158015613753573d6000803e3d6000fd5b505050506040513d602081101561376957600080fd5b505111610e8b576040805160e560020a62461bcd0281526020600482015260116024820152607a60020a7011985a5b1959081d1bc819195c1bdcda5d02604482015290519081900360640190fd5b60008060006137c585612bc0565b92508284116137d457836137d6565b825b91508115156137e457610f81565b6137ee8583614f70565b9050610f8185828511613802576000610f72565b828503613575565b600160a060020a038216151561386a576040805160e560020a62461bcd02815260206004820152601660248201527f52656365697665722063616e2774206265204e756c6c00000000000000000000604482015290519081900360640190fd5b600160a060020a0382163014156138b9576040805160e560020a62461bcd02815260206004820152601c6024820152600080516020615da3833981519152604482015290519081900360640190fd5b6000811161390a576040805160e560020a62461bcd0281526020600482015260136024820152606860020a7252656c61796564207a65726f20746f6b656e7302604482015290519081900360640190fd5b61391381612e3d565b1515613962576040805160e560020a62461bcd0281526020600482015260136024820152606a60020a7214995b185e59590818589bdd99481b1a5b5a5d02604482015290519081900360640190fd5b61396d610deb611684565b610e8b8282613438565b6000806000606060008060008060008060008b8061399957506139998f614ffb565b15156139a457600080fd5b8c600160a060020a0316638d0680436040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156139df57600080fd5b505af11580156139f3573d6000803e3d6000fd5b505050506040513d6020811015613a0957600080fd5b505160018f0151909b5060ff1699508a8a1015613a2557600080fd5b613a2f8f8d615010565b98508a604051908082528060200260200182016040528015613a5b578160200160208202803883390190505b509750600096505b8a871015613bea57866020028a6021010192508960200283019150866002018e01519550828e01519450818e01519350600189878787604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af1158015613b0a573d6000803e3d6000fd5b5050506020604051035190508c600160a060020a031663facd743b826040518263ffffffff1660e01b81526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015613b6e57600080fd5b505af1158015613b82573d6000803e3d6000fd5b505050506040513d6020811015613b9857600080fd5b50511515613ba557600080fd5b613baf8882615240565b15613bb957600080fd5b808888815181101515613bc857fe5b600160a060020a03909216602092830290910190910152600190960195613a63565b505050505050505050505050505050565b6000806000806000613c0c86614ffb565b1515613c1757600080fd5b60148601519450603486015193506054860151925060688601519150607c8601519050855160681415613c555750600080516020615aa38339815191525b91939590929450565b8060046000846040516020018080608860020a6e72656c617965644d6573736167657302815250600f0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b60208310613cd75780518252601f199092019160209182019101613cb8565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff1916941515949094179093555050505050565b6000613d3f600080516020615dc38339815191528461529b565b612a78848484615347565b600080613d5e613d58611684565b866154ae565b50600080516020615dc3833981519152613d78818661529b565b600160a060020a038316600080516020615aa38339815191521415613f24576040805160e060020a63095ea7b3028152600080516020615d438339815191526004820152602481018790529051600160a060020a0383169163095ea7b39160448083019260209291908290030181600087803b158015613df757600080fd5b505af1158015613e0b573d6000803e3d6000fd5b505050506040513d6020811015613e2157600080fd5b50506040805160e460020a63068f3015028152306004820152602481018790529051600080516020615d43833981519152916368f3015091604480830192600092919082900301818387803b158015613e7957600080fd5b505af1158015613e8d573d6000803e3d6000fd5b50506040805160e060020a63a9059cbb028152600160a060020a038a166004820152602481018990529051600080516020615aa3833981519152935063a9059cbb925060448083019260209291908290030181600087803b158015613ef157600080fd5b505af1158015613f05573d6000803e3d6000fd5b505050506040513d6020811015613f1b57600080fd5b50519150613fa3565b600160a060020a038316600080516020615dc383398151915214156103315780600160a060020a031663a9059cbb87876040518363ffffffff1660e01b81526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050602060405180830381600087803b158015613ef157600080fd5b50949350505050565b80600160a060020a0381161515613fc257600080fd5b600160a060020a0383161515613fe057613fdb8261552d565b61108f565b61108f8383615539565b6000903b1190565b60008111613fff57600080fd5b600080516020615c2383398151915260009081526020908152600080516020615c838339815191528290556040805183815290517f4fb76205cd57c896b21511d2114137d8e901b4ccd659e1a0f97d6306795264fb929181900390910190a150565b6000811161406e57600080fd5b6124b2816155d0565b60408101516000108015614092575060408101516020820151115b80156140a2575060208101518151115b15156140ad57600080fd5b8051600080516020615b4383398151915260009081526020818152600080516020615e2383398151915292909255908201516000805160206159c38339815191528252600080516020615ce3833981519152556040820151600080516020615a838339815191528252600080516020615d2383398151915255600080516020615d838339815191529082905b60200201516040518082815260200191505060405180910390a150565b805160208201511061416757600080fd5b8051600080516020615a4383398151915260009081526020818152600080516020615ca38339815191529290925590820151600080516020615e0383398151915282526000805160206159a383398151915255600080516020615983833981519152908290614139565b600160a060020a03811615156141e657600080fd5b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e061420f612149565b60408051600160a060020a03928316815291841660208301528051918290030190a1600080516020615c638339815191526000526002602052600080516020615c438339815191528054600160a060020a031916600160a060020a0392909216919091179055565b600160a060020a038116151561428c57600080fd5b600080516020615a238339815191526000526002602052600080516020615d638339815191528054600160a060020a031916600160a060020a0392909216919091179055565b600080516020615d038339815191526000526004602052600080516020615b63833981519152805460ff19166001179055565b600061430f611fd2565b905080600160a060020a031663ee4937ba6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561434c57600080fd5b505af1158015614360573d6000803e3d6000fd5b505050506040513d602081101561437657600080fd5b50516040805160e160020a630a37fd930281529051600160a060020a03928316926339d0bf63929085169163146ffb26916004808201926020929091908290030181600087803b1580156143c957600080fd5b505af11580156143dd573d6000803e3d6000fd5b505050506040513d60208110156143f357600080fd5b50516040805160e360020a630859bc9d0281529051600160a060020a038616916342cde4e89160048083019260209291908290030181600087803b15801561443a57600080fd5b505af115801561444e573d6000803e3d6000fd5b505050506040513d602081101561446457600080fd5b50516040805160e160020a63290875ab0281529051600160a060020a03871691635210eb569160048083019260209291908290030181600087803b1580156144ab57600080fd5b505af11580156144bf573d6000803e3d6000fd5b505050506040513d60208110156144d557600080fd5b50516040805160e160020a6378a26a4302815290518891600160a060020a0389169163f144d4869160048082019260009290919082900301818387803b15801561451e57600080fd5b505af1158015614532573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561455b57600080fd5b810190808051602060020a81111561457257600080fd5b8201602081018481111561458557600080fd5b81518560208202830111602060020a821117156145a157600080fd5b505092919050505087600160a060020a0316636b6e93d56040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156145e457600080fd5b505af11580156145f8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561462157600080fd5b810190808051602060020a81111561463857600080fd5b8201602081018481111561464b57600080fd5b81518560208202830111602060020a8211171561466757600080fd5b505060405163ffffffff8b1660e01b8152600481018a8152602482018a9052600160a060020a038916604483015260c060648301908152885160c484015288519396509094509250608481019160a482019160e40190602089019080838360005b838110156146e05781810151838201526020016146c8565b50505050905090810190601f16801561470d5780820380516001836020036101000a031916815260200191505b508481038352865181528651602091820191808901910280838360005b8381101561474257818101518382015260200161472a565b50505050905001848103825285818151815260200191508051906020019060200280838360005b83811015614781578181015183820152602001614769565b505050509050019950505050505050505050602060405180830381600087803b1580156147ad57600080fd5b505af11580156147c1573d6000803e3d6000fd5b505050506040513d6020811015611c6057600080fd5b600160a060020a038116301415614826576040805160e560020a62461bcd02815260206004820152601c6024820152600080516020615da3833981519152604482015290519081900360640190fd5b8060026000846040516020018080608160020a6f34b73a32b932b9ba2932b1b2b4bb32b90281525060100182600160a060020a0316600160a060020a031660601b81526014019150506040516020818303038152906040526040518082805190602001908083835b602083106148ad5780518252601f19909201916020918201910161488e565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000208054600160a060020a031916600160a060020a0395909516949094179093555050505050565b80600080846040516020018080608a60020a6e1b5a5b925b9d195c995cdd14185a5902815250600f0182600160a060020a0316600160a060020a031660601b8152601401915050604051602081830303815290604052604051808280519060200190808383602083106133f65780518252601f1990920191602091820191016133d7565b80600080846040516020018080608260020a6f1b5a5b90d85cda151a1c995cda1bdb190281525060100182600160a060020a0316600160a060020a031660601b8152601401915050604051602081830303815290604052604051808280519060200190808383602083106133f65780518252601f1990920191602091820191016133d7565b600160a060020a0316600080516020615dc38339815191521490565b8060046000846040516020018080608a60020a6e1a5b9d195c995cdd115b98589b195902815250600f0182600160a060020a0316600160a060020a031660601b815260140191505060405160208183030381529060405260405180828051906020019080838360208310613cd75780518252601f199092019160209182019101613cb8565b6000614abe611fd2565b905080600160a060020a031663789b11d76040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614afb57600080fd5b505af1158015614b0f573d6000803e3d6000fd5b505050506040513d6020811015614b2557600080fd5b5051600160a060020a031633148015614ba3575080600160a060020a031663146ffb266040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614b7457600080fd5b505af1158015614b88573d6000803e3d6000fd5b505050506040513d6020811015614b9e57600080fd5b505185145b8015614c20575080600160a060020a0316635210eb566040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614be557600080fd5b505af1158015614bf9573d6000803e3d6000fd5b505050506040513d6020811015614c0f57600080fd5b5051600160a060020a038481169116145b8015614c91575080600160a060020a0316632690ff8b6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614c6257600080fd5b505af1158015614c76573d6000803e3d6000fd5b505050506040513d6020811015614c8c57600080fd5b505184145b8015614dac575080600160a060020a031663f238ca266040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614cd357600080fd5b505af1158015614ce7573d6000803e3d6000fd5b505050506040513d6020811015614cfd57600080fd5b5051604051835184916020908101918291848101910280838360005b83811015614d31578181015183820152602001614d19565b505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310614d795780518252601f199092019160209182019101614d5a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916145b1515610f8157600080fd5b8060046000846040516020018080604860020a766d65737361676573417070726f7665644279486173686902815250601701826000191660001916815260200191505060405160208183030381529060405260405180828051906020019080838360208310613cd75780518252601f199092019160209182019101613cb8565b600080516020615bc38339815191526000908152602052600080516020615ac383398151915255565b600160046000836040516020018080607860020a706461746153656e745769746848617368690281525060110182805190602001908083835b60208310614eb85780518252601f199092019160209182019101614e99565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310614f1b5780518252601f199092019160209182019101614efc565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff191694151594909417909355506124b29150829050614305565b6000806000614f7e856134e2565b9150614f8a8585615632565b81614f94866134e2565b03905083811015614fef576040805160e560020a62461bcd02815260206004820152601a60248201527f57697468647261776e206c657373207468616e20416d6f756e74000000000000604482015290519081900360640190fd5b8092505b505092915050565b600081516068148061356f57505051607c1490565b60408051808201909152601a81527f19457468657265756d205369676e6564204d6573736167653a0a0000000000006020820152600090606083156151b6578161505a8651615768565b866040516020018084805190602001908083835b6020831061508d5780518252601f19909201916020918201910161506e565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b602083106150d55780518252601f1990920191602091820191016150b6565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831061511d5780518252601f1990920191602091820191016150fe565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b602083106151825780518252601f199092019160209182019101615163565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209250614ff3565b8451606814156151e35750604080518082019091526003815260ea60020a620c4c0d02602082015261520c565b8451607c14156103315750604080518082019091526003815260ea60020a620c4c8d0260208201525b8181866040516020018084805190602001908083836020831061508d5780518252601f19909201916020918201910161506e565b6000805b835181101561528f5782600160a060020a0316848281518110151561526557fe5b90602001906020020151600160a060020a031614156152875760019150615294565b600101615244565b600091505b5092915050565b6040805160e060020a6370a0823102815230600482015290516000918291600160a060020a038616916370a0823191602480830192602092919082900301818787803b1580156152ea57600080fd5b505af11580156152fe573d6000803e3d6000fd5b505050506040513d602081101561531457600080fd5b5051915082821015611c605761533b61532c85611a04565b8385039063ffffffff61356216565b9050611c6084826137b7565b60008060008061535e615358611684565b876154ae565b615366611243565b600080516020615ae3833981519152600090815260026020908152600080516020615de3833981519152546040805160e060020a63a9059cbb028152600160a060020a039283166004820152602481018b905290519497509087169363a9059cbb93604480840194938390030190829087803b1580156153e557600080fd5b505af11580156153f9573d6000803e3d6000fd5b505050506040513d602081101561540f57600080fd5b50516040805160e060020a63a9059cbb028152600160a060020a038a81166004830152888a03602483015291519294509085169163a9059cbb916044808201926020929091908290030181600087803b15801561546b57600080fd5b505af115801561547f573d6000803e3d6000fd5b505050506040513d602081101561549557600080fd5b505190508180156154a35750805b979650505050505050565b6154bb81610f6684611990565b600080846040516020018080606860020a72746f74616c457865637574656450657244617902815250601301828152602001915050604051602081830303815290604052604051808280519060200190808383602083106133f65780518252601f1990920191602091820191016133d7565b3031610e8b828261583f565b6040805160e060020a6370a0823102815230600482015290518391600091600160a060020a038416916370a0823191602480830192602092919082900301818787803b15801561558857600080fd5b505af115801561559c573d6000803e3d6000fd5b505050506040513d60208110156155b257600080fd5b50519050611c60600160a060020a038516848363ffffffff6158a016565b600080516020615c0383398151915260009081526020908152600080516020615cc38339815191528290556040805183815290517f52264b89e0fceafb26e79fd49ef8a366eb6297483bf4035b027f0c99a7ad512e929181900390910190a150565b600080516020615dc3833981519152600160a060020a0383161461568e576040805160e560020a62461bcd028152602060048201526008602482015260c060020a676e6f74205553445302604482015290519081900360640190fd5b6040805160e260020a632d182be5028152600481018390523060248201819052604482015290516000916000805160206159e38339815191529163b460af949160648082019260209290919082900301818787803b1580156156ef57600080fd5b505af1158015615703573d6000803e3d6000fd5b505050506040513d602081101561571957600080fd5b505111610e8b576040805160e560020a62461bcd0281526020600482015260126024820152607060020a714661696c656420746f20776974686472617702604482015290519081900360640190fd5b6060600080828185151561579857604080518082019091526001815260fc60020a60030260208201529450615836565b8593505b83156157b357600190920191600a8404935061579c565b826040519080825280601f01601f1916602001820160405280156157e1578160200160208202803883390190505b5091505060001982015b85156158325781516000198201916030600a89060160f81b91849190811061580f57fe5b906020010190600160f860020a031916908160001a905350600a860495506157eb565b8194505b50505050919050565b604051600160a060020a0383169082156108fc029083906000818181858888f193505050501515610e8b578082615874615932565b600160a060020a039091168152604051908190036020019082f080158015610f81573d6000803e3d6000fd5b82600160a060020a031663a9059cbb83836040518363ffffffff1660e01b81526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b15801561590057600080fd5b505af1158015615914573d6000803e3d6000fd5b505050503d1561108f5760206000803e600051151561108f57600080fd5b604051602180615942833901905600608060405260405160208060218339810160405251600160a060020a038116ff00b120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b09bebf928b90863f24cc31f726a3a7545efd409f1dcf552301b1ee3710da70d3bf8e983ee86e5e377e9e34c9131b266382c3f04113d20de077f9e12663c7a646b0f8803acad17c63ee38bf2de71e1888bc7a079a6f73658e274b08018bea4e29c000000000000000000000000a3931d71877c0e7a3148cb7eb4463524fec27fbd222cb212229f0f9bcd249029717af6845ea3d3a84f22b54e5744ac25ef224c9271483949fe7a14d16644d63320f24d10cf1d60abecc30cc677a340e82b699dd221dbcab260e413c20dc13c28b7db95e2b423d1135f42bb8b7d5214a92270d237b1578d368dec034f5de4adb7567061a469e92e7039fd319ab435573139ccbcc6bbb088c505d18e049d114c7c91f11724e69c55ad6c5397e2b929e68b41fa05d10000000000000000000000006b175474e89094c44da98b954eedeac495271d0f8ba1484e8bf7939787444e92eb98a67eb881960295fd73460f6d5e6df6d34d1ffefcc139ed357999ed60c6a013947328d52e7d9751e93fd0274a2bfae5cbcb12e66bef0282a446f9848e2903380099bb6e431483ee78778868f33b4a154c818bab54f3fbbe62c59b7876a9bf9bd5e0c22dbae93f4d8ee0438f7ce62b198eb0e04a6a899679f26b73530d8cf1001e83b6f7702e04b6fdb98f3c62dc7e47e041a5078d888f9b66f3f8bfa10909e31f1e16240db73449f0500afdbbe3a70da457cc660d8ed18395a9aa930e304e0bb5e6e51957af1fa215b11db48bfda3dd38d511b3492a958ebdd65bd9a0b8ebca07c67a2ad3af56a28fc2944e214aa69ec9581b8fe4c9f18420598a0f0a5c996b969714f39cc770f1900e60d2697139e137749b4ab7d581336d92edbea22636a613e8e76c99ac7f91137c1523db38dbfb3bf32955b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d79407230071b7802e97e87ef2842a6cce7da7ffaeaedaa2f61a6a7870b23d9d01fc9b73712e02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0d2ea0feb732edb0ffe32efd33a6b9d24d46b16eb34a4d07ce256537b6f131e42add938dbd083a16bae12238cd914fca0afc7a30edb55b1cd5c7f1823f1b0e421f7d5eefab3776d7f0450bd0193564bcb4f832ce313ff2836c450fc63a4b944199de0f81379b4d8e60fe509315d071b56e7b732abaf193e74e0d15808b0951d090a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba8df5c48c6b6e11d97548adc824ba0c99103ec09830fa5d53a179984085e6eaa00000000000000000000000003225737a9bbb6473cb4a45b7244aca2befdb276a21ffdf150a5d180f96d98d16f50e7b4dd63e2a067adc8386cf5af55dcecd8dd9ad4123ae17c414d9c6d2fec478b402e6b01856cc250fd01fbfd252fda0089d3c52656365697665722063616e2774206265207468652042726964676500000000000000000000000000000000dc035d45d973e3ec169d2276ddab16f1e407384ff215aff72f0a1a7d74fcd807336e100b80bbb56cdfb43843ade07ecf211a979fc0ed44c192c86d1cc1ba51340b032c2766b4a2b0041031de13c46dd7104888d51ab29a5cca988aee50edccdd61c5bcaa7ad4b29a03b7ee50f298ceccfe14cc4ea165627a7a723058206d3bf9eb229128196dce5dc14ada05a523133a08c3e79e95a72034085dbc93600029
Deployed Bytecode
0x6080604052600436106103315760003560e01c63ffffffff16806301e4f53a1461033657806303f9c7931461035c5780630fd6d5281461037d5780631b7623be146103925780631dcea427146103b65780631ded8468146103e75780631e86b2911461041057806321d800ec1461043f5780632bd0bb05146104575780633853b7a114610481578063392e53cd146104965780633dd95d1b146104ab5780633e6968b6146104c35780633f0a9f65146104d85780633f7658fd146104ed578063437764df1461051957806343b37dd31461054b5780634774f56314610560578063486ff0cd146105815780634fb3fef71461060b5780635726ff3014610623578063572b6c051461064457806367eeba0c1461066557806369ffa08a1461067a5780636da8b996146106a157806374948c52146106e9578063785b15d5146106fe5780637ea5f8d41461071e57806384fe8ab214610733578063879ce676146107545780638aa1949a1461076c5780638b94e255146107815780638d068043146107965780638da5cb5b146107ab5780638dc8cf87146107c0578063904377ec146107d857806395e54a17146107ff57806399439089146108145780639a454b99146108295780639cb7595a1461083e578063a2a6ca271461087f578063a36b85fd14610897578063a4b4b233146108bb578063a83bb236146108df578063acf5c68914610900578063affed0e014610918578063b20d30a91461092d578063bbc6f1dc14610945578063be22f546146103b6578063bec9fa7c14610969578063bf1fe4201461098a578063c2a2872d146109a2578063c6f6f216146109c6578063c779c1c3146109de578063c8ef95ae146109ff578063cd0fc03314610a14578063ce1b815f14610a43578063cff7744414610a58578063d2ef866014610a79578063d496af2414610a9a578063da74222814610adf578063dae5f0fd14610b00578063df25f3f014610b15578063e0bab4c414610b2a578063ea9f496814610b3f578063ecd9217914610b57578063f20151e114610b6c578063f2fde38b14610b84578063f50dace614610ba5578063f968adbe14610bc6578063fda8babc14610bdb578063fe173b9714610bf0575b600080fd5b34801561034257600080fd5b5061035a600160a060020a0360043516602435610c05565b005b34801561036857600080fd5b5061035a600160a060020a0360043516610e8f565b34801561038957600080fd5b5061035a610f88565b34801561039e57600080fd5b5061035a600160a060020a0360043516602435611094565b3480156103c257600080fd5b506103cb611243565b60408051600160a060020a039092168252519081900360200190f35b3480156103f357600080fd5b506103fc611255565b604080519115158252519081900360200190f35b34801561041c57600080fd5b5061035a602460048035828101929082013591813591820191013560443561125a565b34801561044b57600080fd5b506103fc60043561144a565b34801561046357600080fd5b5061046f600435611508565b60408051918252519081900360200190f35b34801561048d57600080fd5b506103cb6115bb565b3480156104a257600080fd5b506103fc6115cd565b3480156104b757600080fd5b5061035a6004356115fa565b3480156104cf57600080fd5b5061046f611684565b3480156104e457600080fd5b5061046f61168d565b3480156104f957600080fd5b5061035a60246004803582810192908201359181359182019101356116b7565b34801561052557600080fd5b5061052e6118b1565b60408051600160e060020a03199092168252519081900360200190f35b34801561055757600080fd5b5061046f6118bf565b34801561056c57600080fd5b5061046f600160a060020a03600435166118e9565b34801561058d57600080fd5b5061059661196e565b6040805160208082528351818301528351919283929083019185019080838360005b838110156105d05781810151838201526020016105b8565b50505050905090810190601f1680156105fd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561061757600080fd5b5061046f600435611990565b34801561062f57600080fd5b5061046f600160a060020a0360043516611a04565b34801561065057600080fd5b506103fc600160a060020a0360043516611a8a565b34801561067157600080fd5b5061046f611ac2565b34801561068657600080fd5b5061035a600160a060020a0360043581169060243516611aec565b3480156106ad57600080fd5b506103fc600160a060020a03600435811690602435811690604435906064359060849060e4906101243581169061014435906101643516611c66565b3480156106f557600080fd5b5061035a611ebc565b34801561070a57600080fd5b5061035a6004803560248101910135611ed5565b34801561072a57600080fd5b506103cb611fd2565b34801561073f57600080fd5b5061035a600160a060020a0360043516612005565b34801561076057600080fd5b506103fc600435612067565b34801561077857600080fd5b5061046f6120a5565b34801561078d57600080fd5b506103fc6120cf565b3480156107a257600080fd5b5061046f6120d4565b3480156107b757600080fd5b506103cb612149565b3480156107cc57600080fd5b506103fc60043561217c565b3480156107e457600080fd5b5061035a600160a060020a03600435811690602435166121fd565b34801561080b57600080fd5b5061046f612223565b34801561082057600080fd5b506103cb61227d565b34801561083557600080fd5b5061046f6122c2565b34801561084a57600080fd5b506108536122ec565b6040805167ffffffffffffffff9485168152928416602084015292168183015290519081900360600190f35b34801561088b57600080fd5b5061035a6004356122f7565b3480156108a357600080fd5b5061035a600160a060020a036004351660243561236f565b3480156108c757600080fd5b5061035a600160a060020a0360043516602435612395565b3480156108eb57600080fd5b506103cb600160a060020a03600435166123bb565b34801561090c57600080fd5b5061035a60043561248d565b34801561092457600080fd5b5061046f6124b5565b34801561093957600080fd5b5061035a6004356124df565b34801561095157600080fd5b5061046f600160a060020a0360043516602435612569565b34801561097557600080fd5b5061035a600160a060020a036004351661264e565b34801561099657600080fd5b5061035a6004356126b0565b3480156109ae57600080fd5b5061035a600160a060020a03600435166024356126d5565b3480156109d257600080fd5b5061035a6004356128ff565b3480156109ea57600080fd5b5061046f600160a060020a0360043516612973565b348015610a0b57600080fd5b506103cb612a80565b348015610a2057600080fd5b5061035a600160a060020a03600435811690602435906044359060643516612a92565b348015610a4f57600080fd5b506103cb612b8d565b348015610a6457600080fd5b5061046f600160a060020a0360043516612bc0565b348015610a8557600080fd5b506103fc600160a060020a0360043516612c44565b348015610aa657600080fd5b5061059660048035906024803591600160a060020a0360443516916064359160843580830192908201359160a435918201910135612cca565b348015610aeb57600080fd5b5061035a600160a060020a0360043516612d51565b348015610b0c57600080fd5b5061046f612db3565b348015610b2157600080fd5b5061046f612e01565b348015610b3657600080fd5b506103cb612e2b565b348015610b4b57600080fd5b506103fc600435612e3d565b348015610b6357600080fd5b506103cb612e88565b348015610b7857600080fd5b5061035a600435612e9a565b348015610b9057600080fd5b5061035a600160a060020a0360043516612ef2565b348015610bb157600080fd5b5061035a600160a060020a0360043516612f17565b348015610bd257600080fd5b5061046f612f4a565b348015610be757600080fd5b5061035a612f74565b348015610bfc57600080fd5b5061046f61331c565b610c0d613346565b600160a060020a0383811691161415610c70576040805160e560020a62461bcd02815260206004820152601960248201527f52656c6179656420746f20427269646765206164647265737300000000000000604482015290519081900360640190fd5b600160a060020a0382161515610cd0576040805160e560020a62461bcd02815260206004820152601760248201527f52656c6179656420746f204e756c6c2061646472657373000000000000000000604482015290519081900360640190fd5b600160a060020a038216301415610d31576040805160e560020a62461bcd02815260206004820152601760248201527f52656c6179656420746f20746869732061646472657373000000000000000000604482015290519081900360640190fd5b60008111610d81576040805160e560020a62461bcd0281526020600482015260126024820152607060020a7152656c61796564207a65726f2066756e647302604482015290519081900360640190fd5b610d8a81612e3d565b1515610de0576040805160e560020a62461bcd02815260206004820152601a60248201527f4578636565647320627269646765206461696c79206c696d6974000000000000604482015290519081900360640190fd5b610df1610deb611684565b82613379565b610df9611243565b6040805160e060020a6323b872dd028152336004820152306024820152604481018490529051600160a060020a0392909216916323b872dd916064808201926020929091908290030181600087803b158015610e5457600080fd5b505af1158015610e68573d6000803e3d6000fd5b505050506040513d6020811015610e7e57600080fd5b50610e8b90508282613438565b5050565b600080600083610e9e81612c44565b1515610eee576040805160e560020a62461bcd0281526020600482015260146024820152606260020a73125b9d195c995cdd081b9bdd08115b98589b195902604482015290519081900360640190fd5b610ef7856134e2565b9350610f0285611a04565b9250828411610f50576040805160e560020a62461bcd02815260206004820152600f6024820152608860020a6e42616c616e636520746f6f204c6f7702604482015290519081900360640190fd5b8284039150610f7785610f7284610f6689612bc0565b9063ffffffff61356216565b613575565b610f8185836135f8565b5050505050565b6040805160e060020a6370a08231028152306004820152905160009182918291600080516020615dc3833981519152916370a082319160248082019260209290919082900301818787803b158015610fdf57600080fd5b505af1158015610ff3573d6000803e3d6000fd5b505050506040513d602081101561100957600080fd5b50519250611024600080516020615dc3833981519152611a04565b9150818310611073576040805160e560020a62461bcd0281526020600482015260106024820152608260020a6f109c9a5919d9481a5cc8119a5b1b195902604482015290519081900360640190fd5b5081810361108f600080516020615dc3833981519152826137b7565b505050565b6000806000846110a381612c44565b15156110f3576040805160e560020a62461bcd0281526020600482015260146024820152606260020a73125b9d195c995cdd081b9bdd08115b98589b195902604482015290519081900360640190fd5b6110fb611243565b600160a060020a03878116911614611153576040805160e560020a62461bcd0281526020600482015260106024820152608160020a6f2737ba10313934b233b2902a37b5b2b702604482015290519081900360640190fd5b61115c86612973565b935083851061116b578361116d565b845b9250611178866118e9565b8310156111cf576040805160e560020a62461bcd02815260206004820152601c60248201527f436f6c6c65637461626c6520696e74657265737420746f6f206c6f7700000000604482015290519081900360640190fd5b6111e086610f7285610f668a612bc0565b6111e9866123bb565b91506111f5828461380a565b60408051600160a060020a038481168252602082018690528251908916927f222348fe8b30f078a8a4da2f55f16d24d70bc40d3ec49d295d7ad1d11e666887928290030190a2505050505050565b600080516020615dc383398151915290565b600081565b600080600080600061126b33611a8a565b15156112b8576040805160e560020a62461bcd0281526020600482015260116024820152607960020a7034b73b30b634b2103337b93bb0b93232b902604482015290519081900360640190fd5b61132f8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505089898080601f01602080910402602001604051908101604052809392919081815260200183838082843750611328945061227d9350505050565b6000613977565b6113688a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843750613bfb945050505050565b93985091965094509250905061137c611243565b600160a060020a0382811691161461139357600080fd5b61139c84612067565b1561143357838611156113ae57600080fd5b600160a060020a03821630146113c357600080fd5b6113cc8361144a565b156113d657600080fd5b6113e1836001613c5e565b6113ec858588613d25565b15156113f757600080fd5b60408051600160a060020a0387168152602081018690528082018590529051600080516020615be38339815191529181900360600190a161143e565b61143e858585610331565b50505050505050505050565b600060046000836040516020018080608860020a6e72656c617965644d6573736167657302815250600f0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106114c45780518252601f1990920191602091820191016114a5565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1695945050505050565b6000806000836040516020018080608060020a6f746f74616c5370656e74506572446179028152506010018281526020019150506040516020818303038152906040526040518082805190602001908083835b6020831061157a5780518252601f19909201916020918201910161155b565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205495945050505050565b6000805160206159e383398151915290565b600080516020615d038339815191526000526004602052600080516020615b638339815191525460ff1690565b611602612149565b600160a060020a0316331461161657600080fd5b61161e6120a5565b811180611629575080155b151561163457600080fd5b600080516020615a4383398151915260009081526020908152600080516020615ca3833981519152829055604080518381529051600080516020615983833981519152929181900390910190a150565b62015180420490565b600080516020615c238339815191526000908152602052600080516020615c838339815191525490565b6000806000806000806117308a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505089898080601f01602080910402602001604051908101604052809392919081815260200183838082843750611328945061227d9350505050565b6117698a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843750613bfb945050505050565b93995091975095509350915061177e85612067565b156118a657600160a060020a038316301461179857600080fd5b6117a18461144a565b156117ab57600080fd5b6117b6846001613c5e565b60408051600160a060020a03881660601b60208083019190915260348201889052605480830188905283518084039091018152607490920192839052815191929182918401908083835b6020831061181f5780518252601f199092019160209182019101611800565b5181516020939093036101000a60001901801990911692169190911790526040519201829003909120935061185392505050565b61185f86868685613d4a565b151561186a57600080fd5b60408051600160a060020a0388168152602081018790528082018690529051600080516020615be38339815191529181900360600190a161143e565b61143e868686610331565b60e160020a630c3b16a30290565b600080516020615a438339815191526000908152602052600080516020615ca38339815191525490565b6000806000836040516020018080608a60020a6e1b5a5b925b9d195c995cdd14185a5902815250600f0182600160a060020a0316600160a060020a031660601b81526014019150506040516020818303038152906040526040518082805190602001908083836020831061157a5780518252601f19909201916020918201910161155b565b604080518082019091526005815260d860020a64312e302e3102602082015290565b6000806000836040516020018080606860020a72746f74616c4578656375746564506572446179028152506013018281526020019150506040516020818303038152906040526040518082805190602001908083836020831061157a5780518252601f19909201916020918201910161155b565b6000806000836040516020018080608260020a6f1b5a5b90d85cda151a1c995cda1bdb190281525060100182600160a060020a0316600160a060020a031660601b81526014019150506040516020818303038152906040526040518082805190602001908083836020831061157a5780518252601f19909201916020918201910161155b565b600080516020615a038339815191526000526002602052600080516020615ba383398151915254600160a060020a0390811691161490565b600080516020615b438339815191526000908152602052600080516020615e238339815191525490565b60008030600160a060020a0316636fde82026040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b2a57600080fd5b505af1158015611b3e573d6000803e3d6000fd5b505050506040513d6020811015611b5457600080fd5b5051600160a060020a03163314611b6a57600080fd5b50600080516020615dc383398151915290506000805160206159e3833981519152600160a060020a038416821415611be2576040805160e560020a62461bcd0281526020600482015260106024820152608060020a6f43616e277420636c61696d205553445302604482015290519081900360640190fd5b80600160a060020a031684600160a060020a0316141580611c095750611c0782612c44565b155b1515611c56576040805160e560020a62461bcd0281526020600482015260116024820152607860020a7043616e277420636c61696d20735553445302604482015290519081900360640190fd5b611c608484613fac565b50505050565b6040805160048152602481018252602081018051600160e060020a031660e160020a6337ef4101021781529151815160009330939291829190808383895b83811015611cbc578181015183820152602001611ca4565b50505050905090810190601f168015611ce95780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af19150501580611d78575030600160a060020a0316636fde82026040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611d4057600080fd5b505af1158015611d54573d6000803e3d6000fd5b505050506040513d6020811015611d6a57600080fd5b5051600160a060020a031633145b80611d8257503330145b1515611d8d57600080fd5b611d956115cd565b15611d9f57600080fd5b611da88a613fea565b1515611db357600080fd5b611dbb611243565b600160a060020a038a8116911614611dd257600080fd5b8215611ddd57600080fd5b600080516020615b238339815191528054600160a060020a031916600160a060020a038c16179055600080516020615963833981519152600090815260205243600080516020615b0383398151915255611e3688613ff2565b611e3f87614061565b604080516060818101909252611e679188906003908390839080828437506140779350505050565b604080518082018252611e8c9187906002908390839080828437506141569350505050565b611e95846141d1565b611e9e82614277565b611ea66142d2565b611eae6115cd565b9a9950505050505050505050565b611ed3600080516020615dc3833981519152610e8f565b565b6004600083836040516020018080607860020a706461746153656e74576974684861736869028152506011018383808284378201915050925050506040516020818303038152906040526040518082805190602001908083835b60208310611f4e5780518252601f199092019160209182019101611f2f565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1615159250611f9991505057600080fd5b610e8b82828080601f01602080910402602001604051908101604052809392919081815260200183838082843750614305945050505050565b600080516020615b838339815191526000526002602052600080516020615a6383398151915254600160a060020a031690565b61200d612149565b600160a060020a0316331461202157600080fd5b600080516020615ae38339815191526000526002602052600080516020615de38339815191528054600160a060020a031916600160a060020a0392909216919091179055565b60008061207e83610f66612079611684565b611990565b9050806120896118bf565b1015801561209e575061209a6120a5565b8311155b9392505050565b600080516020615e0383398151915260009081526020526000805160206159a38339815191525490565b600181565b60006120de61227d565b600160a060020a0316638d0680436040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561211857600080fd5b505af115801561212c573d6000803e3d6000fd5b505050506040513d602081101561214257600080fd5b5051905090565b600080516020615c638339815191526000526002602052600080516020615c4383398151915254600160a060020a031690565b600060046000836040516020018080604860020a766d65737361676573417070726f76656442794861736869028152506017018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106114c45780518252601f1990920191602091820191016114a5565b612205612149565b600160a060020a0316331461221957600080fd5b610e8b82826147d7565b6000806000806000612233612f4a565b935061223d611ac2565b925061224f61224a611684565b611508565b915081831161225f576000612263565b8183035b90508084106122725780612274565b835b94505050505090565b7f5a74bb7e202fb8e4bf311841c7d64ec19df195fee77d7e7ae749b27921b6ddfe6000526002602052600080516020615b2383398151915254600160a060020a031690565b6000805160206159638339815191526000908152602052600080516020615b038339815191525490565b600660016000909192565b6122ff612149565b600160a060020a0316331461231357600080fd5b6000811180156123295750612326611ac2565b81105b801561233b5750612338612f4a565b81105b151561234657600080fd5b600080516020615a838339815191526000908152602052600080516020615d2383398151915255565b612377612149565b600160a060020a0316331461238b57600080fd5b610e8b828261490a565b61239d612149565b600160a060020a031633146123b157600080fd5b610e8b828261498e565b600060026000836040516020018080608160020a6f34b73a32b932b9ba2932b1b2b4bb32b90281525060100182600160a060020a0316600160a060020a031660601b81526014019150506040516020818303038152906040526040518082805190602001908083835b602083106124435780518252601f199092019160209182019101612424565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a031695945050505050565b612495612149565b600160a060020a031633146124a957600080fd5b6124b281613ff2565b50565b600080516020615bc38339815191526000908152602052600080516020615ac38339815191525490565b6124e7612149565b600160a060020a031633146124fb57600080fd5b612503612f4a565b81118061250e575080155b151561251957600080fd5b600080516020615b4383398151915260009081526020908152600080516020615e23833981519152829055604080518381529051600080516020615d83833981519152929181900390910190a150565b6000600080516020615dc3833981519152600160a060020a038416146125c7576040805160e560020a62461bcd028152602060048201526008602482015260c060020a676e6f74205553445302604482015290519081900360640190fd5b6000805160206159e3833981519152600160a060020a0316630a28a477836040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561261b57600080fd5b505af115801561262f573d6000803e3d6000fd5b505050506040513d602081101561264557600080fd5b50519392505050565b612656612149565b600160a060020a0316331461266a57600080fd5b600080516020615b838339815191526000526002602052600080516020615a638339815191528054600160a060020a031916600160a060020a0392909216919091179055565b6126b8612149565b600160a060020a031633146126cc57600080fd5b6124b281614061565b600080600030600160a060020a0316636fde82026040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561271557600080fd5b505af1158015612729573d6000803e3d6000fd5b505050506040513d602081101561273f57600080fd5b5051600160a060020a0316331461275557600080fd5b6040805160e060020a6370a082310281523060048201529051600080516020615dc3833981519152916370a082319160248083019260209291908290030181600087803b1580156127a557600080fd5b505af11580156127b9573d6000803e3d6000fd5b505050506040513d60208110156127cf57600080fd5b505192506127ea600080516020615dc3833981519152611a04565b9150828410612843576040805160e560020a62461bcd02815260206004820152601860248201527f696e76616c69642077697468647261772062616c616e63650000000000000000604482015290519081900360640190fd5b81848403101561286c578284830103905061286c600080516020615dc3833981519152826137b7565b6040805160e060020a63a9059cbb028152600160a060020a0387166004820152602481018690529051600080516020615dc38339815191529163a9059cbb9160448083019260209291908290030181600087803b1580156128cc57600080fd5b505af11580156128e0573d6000803e3d6000fd5b505050506040513d60208110156128f657600080fd5b50505050505050565b612907612149565b600160a060020a0316331461291b57600080fd5b80158061293f575061292b612e01565b8111801561293f575061293c611ac2565b81105b151561294a57600080fd5b6000805160206159c38339815191526000908152602052600080516020615ce383398151915255565b60008080600080516020615dc3833981519152600160a060020a038516146129d3576040805160e560020a62461bcd028152602060048201526008602482015260c060020a674e6f74205553445302604482015290519081900360640190fd5b6040805160e060020a63ce96cb7702815230600482015290516000805160206159e38339815191529163ce96cb779160248083019260209291908290030181600087803b158015612a2357600080fd5b505af1158015612a37573d6000803e3d6000fd5b505050506040513d6020811015612a4d57600080fd5b50519150612a5a84612bc0565b670de0b6b3a7640000019050808211612a74576000612a78565b8082035b949350505050565b600080516020615dc383398151915281565b612a9a612149565b600160a060020a03163314612aae57600080fd5b612ab784614a13565b1515612b06576040805160e560020a62461bcd0281526020600482015260136024820152606a60020a72151bdad95b881b9bdd081cdd5c1c1bdc9d195902604482015290519081900360640190fd5b612b0f84612c44565b15612b64576040805160e560020a62461bcd02815260206004820152601860248201527f496e74657265737420616c726561647920656e61626c65640000000000000000604482015290519081900360640190fd5b612b6f846001614a2f565b612b79848461498e565b612b83848361490a565b611c6084826147d7565b600080516020615a038339815191526000526002602052600080516020615ba383398151915254600160a060020a031690565b6000806000836040516020018080609260020a6d1a5b9d995cdd1959105b5bdd5b9d02815250600e0182600160a060020a0316600160a060020a031660601b81526014019150506040516020818303038152906040526040518082805190602001908083836020831061157a5780518252601f19909201916020918201910161155b565b600060046000836040516020018080608a60020a6e1a5b9d195c995cdd115b98589b195902815250600f0182600160a060020a0316600160a060020a031660601b8152601401915050604051602081830303815290604052604051808280519060200190808383602083106114c45780518252601f1990920191602091820191016114a5565b60606000612d0789888a89898080602002602001604051908101604052809392919081815260200183836020028082843750614ab4945050505050565b83836040518083838082843782019150509250505060405180910390209050612d2f8161217c565b15612d3957600080fd5b612d44816001614db7565b5098975050505050505050565b612d59612149565b600160a060020a03163314612d6d57600080fd5b600080516020615a038339815191526000526002602052600080516020615ba38339815191528054600160a060020a031916600160a060020a0392909216919091179055565b7f1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee560009081526020527fd5c78dd9468716ca9bb96be25d56436811b20aab3523a9904b12deef1cab239d5490565b600080516020615a838339815191526000908152602052600080516020615d238339815191525490565b600080516020615aa383398151915281565b600080612e4f83610f6661224a611684565b905080612e5a611ac2565b10158015612e6f5750612e6b612f4a565b8311155b801561209e5750612e7e612e01565b9092101592915050565b600080516020615d4383398151915281565b612ea2612149565b600160a060020a03163314612eb657600080fd5b612ebe6118bf565b8110612ec957600080fd5b600080516020615e0383398151915260009081526020526000805160206159a383398151915255565b612efa612149565b600160a060020a03163314612f0e57600080fd5b6124b2816141d1565b612f1f612149565b600160a060020a03163314612f3357600080fd5b612f3f816000196137b7565b6124b2816000614a2f565b6000805160206159c38339815191526000908152602052600080516020615ce38339815191525490565b60408051606860020a72757067726164655f4441495f746f5f55534453028152815190819003601301902060008181526004602052918220549091908190819060ff161561300c576040805160e560020a62461bcd02815260206004820152601d60248201527f5553445320627269646765207567707261646520636f6d706c65746564000000604482015290519081900360640190fd5b6040805160e060020a63ce96cb7702815230600482015290517383f20f44975d03b1b09e64809b757c47f942beea9450849163ce96cb779160248083019260209291908290030181600087803b15801561306557600080fd5b505af1158015613079573d6000803e3d6000fd5b505050506040513d602081101561308f57600080fd5b50516040805160e260020a632d182be502815260048101839052306024820181905260448201529051919350600160a060020a0385169163b460af94916064808201926020929091908290030181600087803b1580156130ee57600080fd5b505af1158015613102573d6000803e3d6000fd5b505050506040513d602081101561311857600080fd5b506131349050600080516020615aa38339815191526000613575565b61314d600080516020615aa38339815191526000614a2f565b613166600080516020615aa3833981519152600061498e565b61317f600080516020615aa3833981519152600061490a565b6040805160e060020a6370a082310281523060048201529051600080516020615aa3833981519152916370a082319160248083019260209291908290030181600087803b1580156131cf57600080fd5b505af11580156131e3573d6000803e3d6000fd5b505050506040513d60208110156131f957600080fd5b50516040805160e060020a63095ea7b3028152600080516020615d438339815191526004820152602481018390529051919250600080516020615aa38339815191529163095ea7b3916044808201926020929091908290030181600087803b15801561326457600080fd5b505af1158015613278573d6000803e3d6000fd5b505050506040513d602081101561328e57600080fd5b50506040805160e160020a6379603d57028152306004820152602481018390529051600080516020615d438339815191529163f2c07aae91604480830192600092919082900301818387803b1580156132e657600080fd5b505af11580156132fa573d6000803e3d6000fd5b505050600094855250506004602052505060409020805460ff19166001179055565b600080516020615c038339815191526000908152602052600080516020615cc38339815191525490565b600080516020615a238339815191526000526002602052600080516020615d6383398151915254600160a060020a031690565b61338681610f6684611508565b600080846040516020018080608060020a6f746f74616c5370656e74506572446179028152506010018281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106133f65780518252601f1990920191602091820191016133d7565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020939093555050505050565b60006134426124b5565b905061345081600101614e37565b60408051600160a060020a038516815260208101849052600083901b8183015290517ff6968e689b3d8c24f22c10c2a3256bb5ca483a474e11bac08423baa049e38ae89181900360600190a160408051600160a060020a03851660601b602082015260348101849052600083901b60548083019190915282518083039091018152607490910190915261108f90614e60565b6040805160e060020a6370a082310281523060048201529051600091600160a060020a038416916370a082319160248082019260209290919082900301818787803b15801561353057600080fd5b505af1158015613544573d6000803e3d6000fd5b505050506040513d602081101561355a57600080fd5b505192915050565b8181018281101561356f57fe5b92915050565b80600080846040516020018080609260020a6d1a5b9d995cdd1959105b5bdd5b9d02815250600e0182600160a060020a0316600160a060020a031660601b8152601401915050604051602081830303815290604052604051808280519060200190808383602083106133f65780518252601f1990920191602091820191016133d7565b600080516020615dc3833981519152600160a060020a03831614613654576040805160e560020a62461bcd028152602060048201526008602482015260c060020a676e6f74205553445302604482015290519081900360640190fd5b6040805160e060020a63095ea7b30281526000805160206159e38339815191526004820152602481018390529051600080516020615dc38339815191529163095ea7b39160448083019260209291908290030181600087803b1580156136b957600080fd5b505af11580156136cd573d6000803e3d6000fd5b505050506040513d60208110156136e357600080fd5b50506040805160e060020a636e553f650281526004810183905230602482015290516000916000805160206159e383398151915291636e553f659160448082019260209290919082900301818787803b15801561373f57600080fd5b505af1158015613753573d6000803e3d6000fd5b505050506040513d602081101561376957600080fd5b505111610e8b576040805160e560020a62461bcd0281526020600482015260116024820152607a60020a7011985a5b1959081d1bc819195c1bdcda5d02604482015290519081900360640190fd5b60008060006137c585612bc0565b92508284116137d457836137d6565b825b91508115156137e457610f81565b6137ee8583614f70565b9050610f8185828511613802576000610f72565b828503613575565b600160a060020a038216151561386a576040805160e560020a62461bcd02815260206004820152601660248201527f52656365697665722063616e2774206265204e756c6c00000000000000000000604482015290519081900360640190fd5b600160a060020a0382163014156138b9576040805160e560020a62461bcd02815260206004820152601c6024820152600080516020615da3833981519152604482015290519081900360640190fd5b6000811161390a576040805160e560020a62461bcd0281526020600482015260136024820152606860020a7252656c61796564207a65726f20746f6b656e7302604482015290519081900360640190fd5b61391381612e3d565b1515613962576040805160e560020a62461bcd0281526020600482015260136024820152606a60020a7214995b185e59590818589bdd99481b1a5b5a5d02604482015290519081900360640190fd5b61396d610deb611684565b610e8b8282613438565b6000806000606060008060008060008060008b8061399957506139998f614ffb565b15156139a457600080fd5b8c600160a060020a0316638d0680436040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156139df57600080fd5b505af11580156139f3573d6000803e3d6000fd5b505050506040513d6020811015613a0957600080fd5b505160018f0151909b5060ff1699508a8a1015613a2557600080fd5b613a2f8f8d615010565b98508a604051908082528060200260200182016040528015613a5b578160200160208202803883390190505b509750600096505b8a871015613bea57866020028a6021010192508960200283019150866002018e01519550828e01519450818e01519350600189878787604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af1158015613b0a573d6000803e3d6000fd5b5050506020604051035190508c600160a060020a031663facd743b826040518263ffffffff1660e01b81526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015613b6e57600080fd5b505af1158015613b82573d6000803e3d6000fd5b505050506040513d6020811015613b9857600080fd5b50511515613ba557600080fd5b613baf8882615240565b15613bb957600080fd5b808888815181101515613bc857fe5b600160a060020a03909216602092830290910190910152600190960195613a63565b505050505050505050505050505050565b6000806000806000613c0c86614ffb565b1515613c1757600080fd5b60148601519450603486015193506054860151925060688601519150607c8601519050855160681415613c555750600080516020615aa38339815191525b91939590929450565b8060046000846040516020018080608860020a6e72656c617965644d6573736167657302815250600f0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b60208310613cd75780518252601f199092019160209182019101613cb8565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff1916941515949094179093555050505050565b6000613d3f600080516020615dc38339815191528461529b565b612a78848484615347565b600080613d5e613d58611684565b866154ae565b50600080516020615dc3833981519152613d78818661529b565b600160a060020a038316600080516020615aa38339815191521415613f24576040805160e060020a63095ea7b3028152600080516020615d438339815191526004820152602481018790529051600160a060020a0383169163095ea7b39160448083019260209291908290030181600087803b158015613df757600080fd5b505af1158015613e0b573d6000803e3d6000fd5b505050506040513d6020811015613e2157600080fd5b50506040805160e460020a63068f3015028152306004820152602481018790529051600080516020615d43833981519152916368f3015091604480830192600092919082900301818387803b158015613e7957600080fd5b505af1158015613e8d573d6000803e3d6000fd5b50506040805160e060020a63a9059cbb028152600160a060020a038a166004820152602481018990529051600080516020615aa3833981519152935063a9059cbb925060448083019260209291908290030181600087803b158015613ef157600080fd5b505af1158015613f05573d6000803e3d6000fd5b505050506040513d6020811015613f1b57600080fd5b50519150613fa3565b600160a060020a038316600080516020615dc383398151915214156103315780600160a060020a031663a9059cbb87876040518363ffffffff1660e01b81526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050602060405180830381600087803b158015613ef157600080fd5b50949350505050565b80600160a060020a0381161515613fc257600080fd5b600160a060020a0383161515613fe057613fdb8261552d565b61108f565b61108f8383615539565b6000903b1190565b60008111613fff57600080fd5b600080516020615c2383398151915260009081526020908152600080516020615c838339815191528290556040805183815290517f4fb76205cd57c896b21511d2114137d8e901b4ccd659e1a0f97d6306795264fb929181900390910190a150565b6000811161406e57600080fd5b6124b2816155d0565b60408101516000108015614092575060408101516020820151115b80156140a2575060208101518151115b15156140ad57600080fd5b8051600080516020615b4383398151915260009081526020818152600080516020615e2383398151915292909255908201516000805160206159c38339815191528252600080516020615ce3833981519152556040820151600080516020615a838339815191528252600080516020615d2383398151915255600080516020615d838339815191529082905b60200201516040518082815260200191505060405180910390a150565b805160208201511061416757600080fd5b8051600080516020615a4383398151915260009081526020818152600080516020615ca38339815191529290925590820151600080516020615e0383398151915282526000805160206159a383398151915255600080516020615983833981519152908290614139565b600160a060020a03811615156141e657600080fd5b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e061420f612149565b60408051600160a060020a03928316815291841660208301528051918290030190a1600080516020615c638339815191526000526002602052600080516020615c438339815191528054600160a060020a031916600160a060020a0392909216919091179055565b600160a060020a038116151561428c57600080fd5b600080516020615a238339815191526000526002602052600080516020615d638339815191528054600160a060020a031916600160a060020a0392909216919091179055565b600080516020615d038339815191526000526004602052600080516020615b63833981519152805460ff19166001179055565b600061430f611fd2565b905080600160a060020a031663ee4937ba6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561434c57600080fd5b505af1158015614360573d6000803e3d6000fd5b505050506040513d602081101561437657600080fd5b50516040805160e160020a630a37fd930281529051600160a060020a03928316926339d0bf63929085169163146ffb26916004808201926020929091908290030181600087803b1580156143c957600080fd5b505af11580156143dd573d6000803e3d6000fd5b505050506040513d60208110156143f357600080fd5b50516040805160e360020a630859bc9d0281529051600160a060020a038616916342cde4e89160048083019260209291908290030181600087803b15801561443a57600080fd5b505af115801561444e573d6000803e3d6000fd5b505050506040513d602081101561446457600080fd5b50516040805160e160020a63290875ab0281529051600160a060020a03871691635210eb569160048083019260209291908290030181600087803b1580156144ab57600080fd5b505af11580156144bf573d6000803e3d6000fd5b505050506040513d60208110156144d557600080fd5b50516040805160e160020a6378a26a4302815290518891600160a060020a0389169163f144d4869160048082019260009290919082900301818387803b15801561451e57600080fd5b505af1158015614532573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561455b57600080fd5b810190808051602060020a81111561457257600080fd5b8201602081018481111561458557600080fd5b81518560208202830111602060020a821117156145a157600080fd5b505092919050505087600160a060020a0316636b6e93d56040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156145e457600080fd5b505af11580156145f8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561462157600080fd5b810190808051602060020a81111561463857600080fd5b8201602081018481111561464b57600080fd5b81518560208202830111602060020a8211171561466757600080fd5b505060405163ffffffff8b1660e01b8152600481018a8152602482018a9052600160a060020a038916604483015260c060648301908152885160c484015288519396509094509250608481019160a482019160e40190602089019080838360005b838110156146e05781810151838201526020016146c8565b50505050905090810190601f16801561470d5780820380516001836020036101000a031916815260200191505b508481038352865181528651602091820191808901910280838360005b8381101561474257818101518382015260200161472a565b50505050905001848103825285818151815260200191508051906020019060200280838360005b83811015614781578181015183820152602001614769565b505050509050019950505050505050505050602060405180830381600087803b1580156147ad57600080fd5b505af11580156147c1573d6000803e3d6000fd5b505050506040513d6020811015611c6057600080fd5b600160a060020a038116301415614826576040805160e560020a62461bcd02815260206004820152601c6024820152600080516020615da3833981519152604482015290519081900360640190fd5b8060026000846040516020018080608160020a6f34b73a32b932b9ba2932b1b2b4bb32b90281525060100182600160a060020a0316600160a060020a031660601b81526014019150506040516020818303038152906040526040518082805190602001908083835b602083106148ad5780518252601f19909201916020918201910161488e565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000208054600160a060020a031916600160a060020a0395909516949094179093555050505050565b80600080846040516020018080608a60020a6e1b5a5b925b9d195c995cdd14185a5902815250600f0182600160a060020a0316600160a060020a031660601b8152601401915050604051602081830303815290604052604051808280519060200190808383602083106133f65780518252601f1990920191602091820191016133d7565b80600080846040516020018080608260020a6f1b5a5b90d85cda151a1c995cda1bdb190281525060100182600160a060020a0316600160a060020a031660601b8152601401915050604051602081830303815290604052604051808280519060200190808383602083106133f65780518252601f1990920191602091820191016133d7565b600160a060020a0316600080516020615dc38339815191521490565b8060046000846040516020018080608a60020a6e1a5b9d195c995cdd115b98589b195902815250600f0182600160a060020a0316600160a060020a031660601b815260140191505060405160208183030381529060405260405180828051906020019080838360208310613cd75780518252601f199092019160209182019101613cb8565b6000614abe611fd2565b905080600160a060020a031663789b11d76040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614afb57600080fd5b505af1158015614b0f573d6000803e3d6000fd5b505050506040513d6020811015614b2557600080fd5b5051600160a060020a031633148015614ba3575080600160a060020a031663146ffb266040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614b7457600080fd5b505af1158015614b88573d6000803e3d6000fd5b505050506040513d6020811015614b9e57600080fd5b505185145b8015614c20575080600160a060020a0316635210eb566040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614be557600080fd5b505af1158015614bf9573d6000803e3d6000fd5b505050506040513d6020811015614c0f57600080fd5b5051600160a060020a038481169116145b8015614c91575080600160a060020a0316632690ff8b6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614c6257600080fd5b505af1158015614c76573d6000803e3d6000fd5b505050506040513d6020811015614c8c57600080fd5b505184145b8015614dac575080600160a060020a031663f238ca266040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614cd357600080fd5b505af1158015614ce7573d6000803e3d6000fd5b505050506040513d6020811015614cfd57600080fd5b5051604051835184916020908101918291848101910280838360005b83811015614d31578181015183820152602001614d19565b505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310614d795780518252601f199092019160209182019101614d5a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916145b1515610f8157600080fd5b8060046000846040516020018080604860020a766d65737361676573417070726f7665644279486173686902815250601701826000191660001916815260200191505060405160208183030381529060405260405180828051906020019080838360208310613cd75780518252601f199092019160209182019101613cb8565b600080516020615bc38339815191526000908152602052600080516020615ac383398151915255565b600160046000836040516020018080607860020a706461746153656e745769746848617368690281525060110182805190602001908083835b60208310614eb85780518252601f199092019160209182019101614e99565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310614f1b5780518252601f199092019160209182019101614efc565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff191694151594909417909355506124b29150829050614305565b6000806000614f7e856134e2565b9150614f8a8585615632565b81614f94866134e2565b03905083811015614fef576040805160e560020a62461bcd02815260206004820152601a60248201527f57697468647261776e206c657373207468616e20416d6f756e74000000000000604482015290519081900360640190fd5b8092505b505092915050565b600081516068148061356f57505051607c1490565b60408051808201909152601a81527f19457468657265756d205369676e6564204d6573736167653a0a0000000000006020820152600090606083156151b6578161505a8651615768565b866040516020018084805190602001908083835b6020831061508d5780518252601f19909201916020918201910161506e565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b602083106150d55780518252601f1990920191602091820191016150b6565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831061511d5780518252601f1990920191602091820191016150fe565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b602083106151825780518252601f199092019160209182019101615163565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209250614ff3565b8451606814156151e35750604080518082019091526003815260ea60020a620c4c0d02602082015261520c565b8451607c14156103315750604080518082019091526003815260ea60020a620c4c8d0260208201525b8181866040516020018084805190602001908083836020831061508d5780518252601f19909201916020918201910161506e565b6000805b835181101561528f5782600160a060020a0316848281518110151561526557fe5b90602001906020020151600160a060020a031614156152875760019150615294565b600101615244565b600091505b5092915050565b6040805160e060020a6370a0823102815230600482015290516000918291600160a060020a038616916370a0823191602480830192602092919082900301818787803b1580156152ea57600080fd5b505af11580156152fe573d6000803e3d6000fd5b505050506040513d602081101561531457600080fd5b5051915082821015611c605761533b61532c85611a04565b8385039063ffffffff61356216565b9050611c6084826137b7565b60008060008061535e615358611684565b876154ae565b615366611243565b600080516020615ae3833981519152600090815260026020908152600080516020615de3833981519152546040805160e060020a63a9059cbb028152600160a060020a039283166004820152602481018b905290519497509087169363a9059cbb93604480840194938390030190829087803b1580156153e557600080fd5b505af11580156153f9573d6000803e3d6000fd5b505050506040513d602081101561540f57600080fd5b50516040805160e060020a63a9059cbb028152600160a060020a038a81166004830152888a03602483015291519294509085169163a9059cbb916044808201926020929091908290030181600087803b15801561546b57600080fd5b505af115801561547f573d6000803e3d6000fd5b505050506040513d602081101561549557600080fd5b505190508180156154a35750805b979650505050505050565b6154bb81610f6684611990565b600080846040516020018080606860020a72746f74616c457865637574656450657244617902815250601301828152602001915050604051602081830303815290604052604051808280519060200190808383602083106133f65780518252601f1990920191602091820191016133d7565b3031610e8b828261583f565b6040805160e060020a6370a0823102815230600482015290518391600091600160a060020a038416916370a0823191602480830192602092919082900301818787803b15801561558857600080fd5b505af115801561559c573d6000803e3d6000fd5b505050506040513d60208110156155b257600080fd5b50519050611c60600160a060020a038516848363ffffffff6158a016565b600080516020615c0383398151915260009081526020908152600080516020615cc38339815191528290556040805183815290517f52264b89e0fceafb26e79fd49ef8a366eb6297483bf4035b027f0c99a7ad512e929181900390910190a150565b600080516020615dc3833981519152600160a060020a0383161461568e576040805160e560020a62461bcd028152602060048201526008602482015260c060020a676e6f74205553445302604482015290519081900360640190fd5b6040805160e260020a632d182be5028152600481018390523060248201819052604482015290516000916000805160206159e38339815191529163b460af949160648082019260209290919082900301818787803b1580156156ef57600080fd5b505af1158015615703573d6000803e3d6000fd5b505050506040513d602081101561571957600080fd5b505111610e8b576040805160e560020a62461bcd0281526020600482015260126024820152607060020a714661696c656420746f20776974686472617702604482015290519081900360640190fd5b6060600080828185151561579857604080518082019091526001815260fc60020a60030260208201529450615836565b8593505b83156157b357600190920191600a8404935061579c565b826040519080825280601f01601f1916602001820160405280156157e1578160200160208202803883390190505b5091505060001982015b85156158325781516000198201916030600a89060160f81b91849190811061580f57fe5b906020010190600160f860020a031916908160001a905350600a860495506157eb565b8194505b50505050919050565b604051600160a060020a0383169082156108fc029083906000818181858888f193505050501515610e8b578082615874615932565b600160a060020a039091168152604051908190036020019082f080158015610f81573d6000803e3d6000fd5b82600160a060020a031663a9059cbb83836040518363ffffffff1660e01b81526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b15801561590057600080fd5b505af1158015615914573d6000803e3d6000fd5b505050503d1561108f5760206000803e600051151561108f57600080fd5b604051602180615942833901905600608060405260405160208060218339810160405251600160a060020a038116ff00b120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b09bebf928b90863f24cc31f726a3a7545efd409f1dcf552301b1ee3710da70d3bf8e983ee86e5e377e9e34c9131b266382c3f04113d20de077f9e12663c7a646b0f8803acad17c63ee38bf2de71e1888bc7a079a6f73658e274b08018bea4e29c000000000000000000000000a3931d71877c0e7a3148cb7eb4463524fec27fbd222cb212229f0f9bcd249029717af6845ea3d3a84f22b54e5744ac25ef224c9271483949fe7a14d16644d63320f24d10cf1d60abecc30cc677a340e82b699dd221dbcab260e413c20dc13c28b7db95e2b423d1135f42bb8b7d5214a92270d237b1578d368dec034f5de4adb7567061a469e92e7039fd319ab435573139ccbcc6bbb088c505d18e049d114c7c91f11724e69c55ad6c5397e2b929e68b41fa05d10000000000000000000000006b175474e89094c44da98b954eedeac495271d0f8ba1484e8bf7939787444e92eb98a67eb881960295fd73460f6d5e6df6d34d1ffefcc139ed357999ed60c6a013947328d52e7d9751e93fd0274a2bfae5cbcb12e66bef0282a446f9848e2903380099bb6e431483ee78778868f33b4a154c818bab54f3fbbe62c59b7876a9bf9bd5e0c22dbae93f4d8ee0438f7ce62b198eb0e04a6a899679f26b73530d8cf1001e83b6f7702e04b6fdb98f3c62dc7e47e041a5078d888f9b66f3f8bfa10909e31f1e16240db73449f0500afdbbe3a70da457cc660d8ed18395a9aa930e304e0bb5e6e51957af1fa215b11db48bfda3dd38d511b3492a958ebdd65bd9a0b8ebca07c67a2ad3af56a28fc2944e214aa69ec9581b8fe4c9f18420598a0f0a5c996b969714f39cc770f1900e60d2697139e137749b4ab7d581336d92edbea22636a613e8e76c99ac7f91137c1523db38dbfb3bf32955b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d79407230071b7802e97e87ef2842a6cce7da7ffaeaedaa2f61a6a7870b23d9d01fc9b73712e02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0d2ea0feb732edb0ffe32efd33a6b9d24d46b16eb34a4d07ce256537b6f131e42add938dbd083a16bae12238cd914fca0afc7a30edb55b1cd5c7f1823f1b0e421f7d5eefab3776d7f0450bd0193564bcb4f832ce313ff2836c450fc63a4b944199de0f81379b4d8e60fe509315d071b56e7b732abaf193e74e0d15808b0951d090a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba8df5c48c6b6e11d97548adc824ba0c99103ec09830fa5d53a179984085e6eaa00000000000000000000000003225737a9bbb6473cb4a45b7244aca2befdb276a21ffdf150a5d180f96d98d16f50e7b4dd63e2a067adc8386cf5af55dcecd8dd9ad4123ae17c414d9c6d2fec478b402e6b01856cc250fd01fbfd252fda0089d3c52656365697665722063616e2774206265207468652042726964676500000000000000000000000000000000dc035d45d973e3ec169d2276ddab16f1e407384ff215aff72f0a1a7d74fcd807336e100b80bbb56cdfb43843ade07ecf211a979fc0ed44c192c86d1cc1ba51340b032c2766b4a2b0041031de13c46dd7104888d51ab29a5cca988aee50edccdd61c5bcaa7ad4b29a03b7ee50f298ceccfe14cc4ea165627a7a723058206d3bf9eb229128196dce5dc14ada05a523133a08c3e79e95a72034085dbc93600029
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.