ETH Price: $3,469.53 (+5.22%)

Contract

0x1Faa9AC72E58F84373FB60d9e9f5257170e688F7
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw129194282021-07-29 7:37:431268 days ago1627544263IN
0x1Faa9AC7...170e688F7
0 ETH0.0021581430
Deposit120647072021-03-18 19:57:461401 days ago1616097466IN
0x1Faa9AC7...170e688F7
0.0238 ETH0.03060995206
Withdraw119990522021-03-08 17:02:161411 days ago1615222936IN
0x1Faa9AC7...170e688F7
0 ETH0.0121876200
Deposit119925622021-03-07 17:01:411412 days ago1615136501IN
0x1Faa9AC7...170e688F7
0.0535 ETH0.02719233183
Withdraw119925272021-03-07 16:53:371412 days ago1615136017IN
0x1Faa9AC7...170e688F7
0 ETH0.01096884180
Deposit119912992021-03-07 12:19:261412 days ago1615119566IN
0x1Faa9AC7...170e688F7
0.0428 ETH0.02332451110
Withdraw113560732020-11-29 21:44:371510 days ago1606686277IN
0x1Faa9AC7...170e688F7
0 ETH0.0010966618
Deposit113495732020-11-28 21:43:091511 days ago1606599789IN
0x1Faa9AC7...170e688F7
0.045 ETH0.0046646322
Withdraw110867312020-10-19 13:40:441551 days ago1603114844IN
0x1Faa9AC7...170e688F7
0 ETH0.01005316130
Withdraw107170162020-08-23 14:08:561608 days ago1598191736IN
0x1Faa9AC7...170e688F7
0 ETH0.0054844290
Deposit107170022020-08-23 14:03:361608 days ago1598191416IN
0x1Faa9AC7...170e688F7
0.20926674 ETH0.0190836990
Deposit106799732020-08-17 21:28:181614 days ago1597699698IN
0x1Faa9AC7...170e688F7
0 ETH0.0200028382
Withdraw104317232020-07-10 12:19:451652 days ago1594383585IN
0x1Faa9AC7...170e688F7
0 ETH0.0023765839
Deposit104258732020-07-09 14:40:181653 days ago1594305618IN
0x1Faa9AC7...170e688F7
1 ETH0.0090641161
Redeem102430532020-06-11 7:26:071681 days ago1591860367IN
0x1Faa9AC7...170e688F7
0 ETH0.0021566536
Initiate102430172020-06-11 7:18:441681 days ago1591859924IN
0x1Faa9AC7...170e688F7
0 ETH0.0106367736
Deposit102401412020-06-10 20:34:321682 days ago1591821272IN
0x1Faa9AC7...170e688F7
1.575 ETH0.0043091629
Redeem102399152020-06-10 19:44:491682 days ago1591818289IN
0x1Faa9AC7...170e688F7
0 ETH0.0020967435
Initiate102398812020-06-10 19:36:551682 days ago1591817815IN
0x1Faa9AC7...170e688F7
0 ETH0.0103413135
Deposit102394052020-06-10 17:54:451682 days ago1591811685IN
0x1Faa9AC7...170e688F7
1.575 ETH0.0069838247
Withdraw102393752020-06-10 17:47:281682 days ago1591811248IN
0x1Faa9AC7...170e688F7
0 ETH0.0028640847
Deposit102390672020-06-10 16:37:221682 days ago1591807042IN
0x1Faa9AC7...170e688F7
1.6 ETH0.007429650
Redeem101619212020-05-29 17:10:471694 days ago1590772247IN
0x1Faa9AC7...170e688F7
0 ETH0.002395840
Initiate101618832020-05-29 17:01:091694 days ago1590771669IN
0x1Faa9AC7...170e688F7
0 ETH0.0118181640
Deposit101612372020-05-29 14:33:191694 days ago1590762799IN
0x1Faa9AC7...170e688F7
1.35 ETH0.0059436840
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
129194282021-07-29 7:37:431268 days ago1627544263
0x1Faa9AC7...170e688F7
0.0238 ETH
119990522021-03-08 17:02:161411 days ago1615222936
0x1Faa9AC7...170e688F7
0.0535 ETH
119925272021-03-07 16:53:371412 days ago1615136017
0x1Faa9AC7...170e688F7
0.0428 ETH
113560732020-11-29 21:44:371510 days ago1606686277
0x1Faa9AC7...170e688F7
0.045 ETH
107170162020-08-23 14:08:561608 days ago1598191736
0x1Faa9AC7...170e688F7
0.20926674 ETH
104317232020-07-10 12:19:451652 days ago1594383585
0x1Faa9AC7...170e688F7
1 ETH
102430532020-06-11 7:26:071681 days ago1591860367
0x1Faa9AC7...170e688F7
1.575 ETH
102399152020-06-10 19:44:491682 days ago1591818289
0x1Faa9AC7...170e688F7
1.575 ETH
102393752020-06-10 17:47:281682 days ago1591811248
0x1Faa9AC7...170e688F7
1.6 ETH
101619212020-05-29 17:10:471694 days ago1590772247
0x1Faa9AC7...170e688F7
1.35 ETH
101609782020-05-29 13:35:541694 days ago1590759354
0x1Faa9AC7...170e688F7
12.625 ETH
101395502020-05-26 5:47:221697 days ago1590472042
0x1Faa9AC7...170e688F7
7 ETH
101231612020-05-23 16:19:501700 days ago1590250790
0x1Faa9AC7...170e688F7
2.58 ETH
101229782020-05-23 15:36:501700 days ago1590248210
0x1Faa9AC7...170e688F7
2.022 ETH
101227052020-05-23 14:38:371700 days ago1590244717
0x1Faa9AC7...170e688F7
2.025 ETH
101226092020-05-23 14:20:401700 days ago1590243640
0x1Faa9AC7...170e688F7
0.045 ETH
101159642020-05-22 13:36:391701 days ago1590154599
0x1Faa9AC7...170e688F7
3.2 ETH
101158672020-05-22 13:12:001701 days ago1590153120
0x1Faa9AC7...170e688F7
3.2625 ETH
101152002020-05-22 10:34:211701 days ago1590143661
0x1Faa9AC7...170e688F7
0.175 ETH
101133832020-05-22 3:41:201701 days ago1590118880
0x1Faa9AC7...170e688F7
0.84 ETH
101133632020-05-22 3:38:251701 days ago1590118705
0x1Faa9AC7...170e688F7
0.858 ETH
101133632020-05-22 3:38:251701 days ago1590118705
0x1Faa9AC7...170e688F7
1.56 ETH
101133442020-05-22 3:34:511701 days ago1590118491
0x1Faa9AC7...170e688F7
0.1875 ETH
101132952020-05-22 3:24:521701 days ago1590117892
0x1Faa9AC7...170e688F7
0.8316 ETH
95981882020-03-03 12:31:071781 days ago1583238667
0x1Faa9AC7...170e688F7
0.27 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AdminUpgradeabilityProxy

Compiler Version
v0.5.12+commit.7709ece9

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-02-19
*/

pragma solidity 0.5.12;

/**
 * @title SafeMath
 * @dev Unsigned math operations with safety checks that revert on error
 */
library SafeMath {
    /**
     * @dev Multiplies two unsigned integers, reverts on overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring '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;
        }

        uint256 c = a * b;
        require(c / a == b);

        return c;
    }

    /**
     * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Adds two unsigned integers, reverts on overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);

        return c;
    }

    /**
     * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
     * reverts when dividing by zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0);
        return a % b;
    }
}

/**
 * Utility library of inline functions on addresses
 */
library Address {
    /**
     * 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 account address of the account to check
     * @return whether the target address is a contract
     */
    function isContract(address account) 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.
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }
}

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
contract Context {
    // Empty internal constructor, to prevent people from mistakenly deploying
    // an instance of this contract, which should be used via inheritance.
    constructor () internal { }
    // solhint-disable-previous-line no-empty-blocks

    function _msgSender() internal view returns (address payable) {
        return msg.sender;
    }

    function _msgValue() internal view returns (uint256) {
        return msg.value;
    }
}

/**
 * @title ERC20 interface
 * @dev see https://eips.ethereum.org/EIPS/eip-20
 */
interface IERC20 {
    function transfer(address to, uint256 value) external returns (bool);

    function approve(address spender, uint256 value) external returns (bool);

    function transferFrom(address from, address to, uint256 value) external returns (bool);

    function totalSupply() external view returns (uint256);

    function balanceOf(address who) external view returns (uint256);

    function allowance(address owner, address spender) external view returns (uint256);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require((value == 0) || (token.allowance(address(this), spender) == 0));
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value);
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must equal true).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves.

        // A Solidity high level call has three parts:
        //  1. The target address is checked to verify it contains contract code
        //  2. The call itself is made, and success asserted
        //  3. The return value is decoded, which in turn checks the size of the returned data.

        require(address(token).isContract());

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success);

        if (returndata.length > 0) { // Return data is optional
            require(abi.decode(returndata, (bool)));
        }
    }
}

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev The Ownable constructor sets the original `owner` of the contract to the sender
     * account.
     */
    constructor () internal {
        _owner = _msgSender();
        emit OwnershipTransferred(address(0), _owner);
    }

    /**
     * @return the address of the owner.
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(isOwner());
        _;
    }

    /**
     * @return true if `msg.sender` is the owner of the contract.
     */
    function isOwner() public view returns (bool) {
        return _msgSender() == _owner;
    }

    /**
     * @dev Allows the current owner to relinquish control of the contract.
     * It will not be possible to call the functions with the `onlyOwner`
     * modifier anymore.
     * @notice Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @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) public onlyOwner {
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers control of the contract to a newOwner.
     * @param newOwner The address to transfer ownership to.
     */
    function _transferOwnership(address newOwner) internal {
        require(newOwner != address(0));
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

/**
 * @title EternalStorage
 * @dev Store the all information about  users and orders
 */
contract EternalStorage is Ownable {
    // Count of users who is or was active
    uint256 internal _usersCount;

    // Count of deposits
    uint256 internal _depositsCount;

    // Count of swaps
    uint256 internal _swapsCount;

    // The id for ETH asset is 0x0 address
    // the rest assets should have their token contract address
    address internal _ethAssetIdentificator = address(0);

    // Order details which is available by JAVA long number
    struct OrderDetails {
        // does the order has been deposited
        bool created;
        // the 0x0 for Ethereum and ERC contract address for tokens
        address asset;
        // tokens/eth amount
        uint256 amount;
        // the status (deposited/withdrawn)
        bool withdrawn;
        // creation timestamp
        uint256 initTimestamp;
    }

    // Each user has his own state and details
    struct User {
        // user exist validation bool
        bool exist;
        // contract order index
        uint256 index;
        // contract index (0, 1, 2 ...) => exchange order number (JAVA long number)
        mapping(uint256 => uint256) orderIdByIndex;
        // JAVA long number => order details
        mapping(uint256 => OrderDetails) orders;
    }

    // the body of each swap
    struct Swap {
        uint256 initTimestamp;
        uint256 refundTimestamp;
        bytes32 secretHash;
        bytes32 secret;
        address initiator;
        address recipient;
        address asset;
        uint256 amount;
        uint256 orderId;
        State state;
    }

    // struct of swap Initiator
    struct Initiator {
        // contract order index
        uint256 index;
        // length of filled swaps
        uint256 filledSwaps;
        // index (0, 1, 2 ...) => swap hash
        mapping(uint256 => bytes32) swaps;
    }

    // min/max life limits for swap order
    // can be changed only by the contract owner
    struct SwapTimeLimits {
        uint256 min;
        uint256 max;
    }

    // ETH wallet => Assets => value
    mapping(address => User) internal _users;

    // Id => Address of user
    mapping(uint256 => address) internal _usersById;

    // Id => Swap secret hash
    mapping(uint256 => bytes32) internal _swapsById;

    // Id => Order id
    mapping(uint256 => uint256) internal _depositsById;

    // mapping of swaps based on secret hash and swap info
    mapping(bytes32 => Swap) internal _swaps;

    // the swaps data by initiator address
    mapping(address => Initiator) internal _initiators;

    // swaps' state
    enum State { Empty, Filled, Redeemed, Refunded }

    // users can swap ETH and ERC tokens
    enum SwapType { ETH, Token }

    // By default, the contract has limits for swap orders lifetime
    // The swap order can be active from 10 minutes until 6 months
    SwapTimeLimits internal _swapTimeLimits = SwapTimeLimits(10 minutes, 180 days);

    // -----------------------------------------
    // ADMIN METHODS
    // -----------------------------------------

    /**
     *  @dev The owner can change time limits for swap lifetime
     *  Amounts should be written in MINUTES
     */
    function changeSwapLifetimeLimits(
        uint256 newMin,
        uint256 newMax
    ) external onlyOwner {
        require(newMin != 0, "changeSwapLifetimeLimits: newMin and newMax should be bigger then 0");
        require(newMax >= newMin, "changeSwapLifetimeLimits: the newMax should be bigger then newMax");

        _swapTimeLimits = SwapTimeLimits(newMin * 1 minutes, newMax * 1 minutes);
    }
}

/**
 * @title Proxy
 * @dev Implements delegation of calls to other contracts, with proper
 * forwarding of return values and bubbling of failures.
 * It defines a fallback function that delegates all calls to the address
 * returned by the abstract _implementation() internal function.
 */
contract Proxy is EternalStorage {
	/**
	 * @dev Fallback function.
	 * Implemented entirely in `_fallback`.
	 */
	function () payable external {
		_fallback();
	}

	/**
	 * @dev fallback implementation.
	 * Extracted to enable manual triggering.
	 */
	function _fallback() internal {
		_willFallback();
		_delegate(_implementation());
	}

	/**
	 * @dev Function that is run as the first thing in the fallback function.
	 * Can be redefined in derived contracts to add functionality.
	 * Redefinitions must call super._willFallback().
	 */
	function _willFallback() internal {}

	/**
	 * @dev Delegates execution to an implementation contract.
	 * This is a low level function that doesn't return to its internal call site.
	 * It will return to the external caller whatever the implementation returns.
	 * @param implementation Address to delegate.
	 */
	function _delegate(address implementation) internal {
		assembly {
			// Copy msg.data. We take full control of memory in this inline assembly
			// block because it will not return to Solidity code. We overwrite the
			// Solidity scratch pad at memory position 0.
			calldatacopy(0, 0, calldatasize)

			// Call the implementation.
			// out and outsize are 0 because we don't know the size yet.
			let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)

			// Copy the returned data.
			returndatacopy(0, 0, returndatasize)

			switch result
			// delegatecall returns 0 on error.
			case 0 { revert(0, returndatasize) }
			default { return(0, returndatasize) }
		}
  	}

	/**
	 * @return The Address of the implementation.
	 */
	function _implementation() internal view returns (address);
}

/**
 * @title BaseUpgradeabilityProxy
 * @dev This contract implements a proxy that allows to change the
 * implementation address to which it will delegate.
 * Such a change is called an implementation upgrade.
 */
contract BaseUpgradeabilityProxy is Proxy {
	using Address for address;

	/**
	 * @dev The version of current(active) logic contract
	 */
    string internal _version;

	/**
	 * @dev Storage slot with the address of the current implementation.
	 * This is the keccak-256 hash of "org.zeppelinos.proxy.implementation", and is
	 * validated in the constructor.
	 */
	bytes32 internal constant IMPLEMENTATION_SLOT = 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3;

	/**
	 * @dev Emitted when the implementation is upgraded.
	 * @param implementation Address of the new implementation.
	 */
	event Upgraded(address indexed implementation);

	/**
	 * @dev Returns the current implementation.
	 * @return Address of the current implementation
	 */
	function _implementation() internal view returns (address impl) {
		bytes32 slot = IMPLEMENTATION_SLOT;
		assembly {
		    impl := sload(slot)
		}
	}

	/**
	 * @dev Upgrades the proxy to a new implementation.
	 * @param newImplementation Address of the new implementation.
	 * @param newVersion of proxied contract.
	 */
	function _upgradeTo(address newImplementation, string memory newVersion) internal {
		_setImplementation(newImplementation, newVersion);

		emit Upgraded(newImplementation);
	}

	/**
	 * @dev Sets the implementation address of the proxy.
	 * @param newImplementation Address of the new implementation.
	 * @param newVersion of proxied contract.
	 */
	function _setImplementation(address newImplementation, string memory newVersion) internal {
		require(newImplementation.isContract(), "Cannot set a proxy implementation to a non-contract address");

 		_version = newVersion;

		bytes32 slot = IMPLEMENTATION_SLOT;

		assembly {
		    sstore(slot, newImplementation)
		}
	}
}

/**
 * @title UpgradeabilityProxy
 * @dev Extends BaseUpgradeabilityProxy with a constructor for initializing
 * implementation and init data.
 */
contract UpgradeabilityProxy is BaseUpgradeabilityProxy {
	/**
	 * @dev Contract constructor.
	 * @param _logic Address of the initial implementation.
	 */
	constructor(address _logic) public payable {
		assert(IMPLEMENTATION_SLOT == keccak256("org.zeppelinos.proxy.implementation"));
		_setImplementation(_logic, '1.0.0');
	}
}

/**
 * @title BaseAdminUpgradeabilityProxy
 * @dev This contract combines an upgradeability proxy with an authorization
 * mechanism for administrative tasks.
 * All external functions in this contract must be guarded by the
 * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity
 * feature proposal that would enable this to be done automatically.
 */
contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {
	/**
	 * @dev Emitted when the administration has been transferred.
	 * @param previousAdmin Address of the previous admin.
	 * @param newAdmin Address of the new admin.
	 */
	event AdminChanged(address previousAdmin, address newAdmin);

	/**
	 * @dev Storage slot with the admin of the contract.
	 * This is the keccak-256 hash of "org.zeppelinos.proxy.admin", and is
	 * validated in the constructor.
	 */
  	bytes32 internal constant ADMIN_SLOT = 0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b;

  	/**
	 * @dev Modifier to check whether the `msg.sender` is the admin.
	 * If it is, it will run the function. Otherwise, it will delegate the call
	 * to the implementation.
	 */
	modifier ifAdmin() {
		if (msg.sender == _admin()) {
		    _;
		} else {
		    _fallback();
		}
	}

	/**
	 * @return The address of the proxy admin.
	 */
	function admin() external view returns (address) {
		return _admin();
	}

	/**
	 * @return The version of logic contract
	 */
	function version() external view returns (string memory) {
		return _version;
	}

	/**
	 * @return The address of the implementation.
	 */
	function implementation() external view returns (address) {
		return _implementation();
	}

	/**
	 * @dev Changes the admin of the proxy.
	 * Only the current admin can call this function.
	 * @param newAdmin Address to transfer proxy administration to.
	 */
	function changeAdmin(address newAdmin) external ifAdmin {
		require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
		emit AdminChanged(_admin(), newAdmin);
		_setAdmin(newAdmin);
	}

	/**
	 * @dev Upgrade the backing implementation of the proxy.
	 * Only the admin can call this function.
	 * @param newImplementation Address of the new implementation.
	 * @param newVersion of proxied contract.
	 */
	function upgradeTo(address newImplementation, string calldata newVersion) external ifAdmin {
		_upgradeTo(newImplementation, newVersion);
	}

	/**
	 * @dev Upgrade the backing implementation of the proxy and call a function
	 * on the new implementation.
	 * This is useful to initialize the proxied contract.
	 * @param newImplementation Address of the new implementation.
	 * @param newVersion of proxied contract.
	 * @param data Data to send as msg.data in the low level call.
	 * It should include the signature and the parameters of the function to be called, as described in
	 * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
	 */
	function upgradeToAndCall(address newImplementation, string calldata newVersion, bytes calldata data) payable external ifAdmin {
		_upgradeTo(newImplementation, newVersion);
		(bool success,) = newImplementation.delegatecall(data);
		require(success);
	}

	/**
	 * @return The admin slot.
	 */
	function _admin() internal view returns (address adm) {
		bytes32 slot = ADMIN_SLOT;
		assembly {
    		adm := sload(slot)
		}
	}

	/**
	 * @dev Sets the address of the proxy admin.
	 * @param newAdmin Address of the new proxy admin.
	 */
	function _setAdmin(address newAdmin) internal {
		bytes32 slot = ADMIN_SLOT;

		assembly {
			sstore(slot, newAdmin)
		}
	}

	/**
	 * @dev Only fall back when the sender is not the admin.
	 */
	function _willFallback() internal {
		require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
		super._willFallback();
	}
}

/**
 * @title AdminUpgradeabilityProxy
 * @dev Extends from BaseAdminUpgradeabilityProxy with a constructor for
 * initializing the implementation, admin, and init data.
 */
contract AdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, UpgradeabilityProxy {
	/**
	 * Contract constructor.
	 * @param _logic address of the initial implementation.
	 * @param _admin Address of the proxy administrator.
	 */
	constructor(address _logic, address _admin) UpgradeabilityProxy(_logic) public payable {
		assert(ADMIN_SLOT == keccak256("org.zeppelinos.proxy.admin"));
		_setAdmin(_admin);
	}
}

/**
 * @title AssetsValue
 * @dev The contract which hold all tokens and ETH as a assets
 * Also should be responsible for the balance increasing/decreasing and validation
 */
contract AssetsValue is EternalStorage {
    // using safe math calculation
    using SafeMath for uint256;

    // for being secure during transactions between users and contract gonna use SafeERC20 lib
    using SafeERC20 for IERC20;

    modifier orderIdNotExist(
        uint256 orderId,
        address user
    ) {
        require(_getOrderDetails(orderId, user).created == false, "orderIdNotExist: user already deposit this orderId");
        _;
    }

    // Events
    event AssetDeposited(uint256 orderId, address indexed user, address indexed asset, uint256 amount);
    event AssetWithdrawal(uint256 orderId, address indexed user, address indexed asset, uint256 amount);

    // -----------------------------------------
    // FALLBACK
    // -----------------------------------------

    function () external payable {
        // reverts all fallback & payable transactions
        revert("Fallback methods should be reverted");
    }

    // -----------------------------------------
    // EXTERNAL
    // -----------------------------------------

    function deposit(
        uint256 orderId
    ) public orderIdNotExist(orderId, _msgSender()) payable {
        require(_msgValue() != 0, "deposit: user needs to transfer ETH for calling this method");

        _deposit(orderId, _msgSender(), _ethAssetIdentificator, _msgValue());
    }

    function deposit(
        uint256 orderId,
        uint256 amount,
        address token
    ) public orderIdNotExist(orderId, _msgSender()) {
        require(token != address(0), "deposit: invalid token address");
        require(amount != 0, "deposit: user needs to fill transferable tokens amount for calling this method");

        IERC20(token).safeTransferFrom(_msgSender(), address(this), amount);
        _deposit(orderId, _msgSender(), token, amount);
    }

    function withdraw(
        uint256 orderId
    ) external {
        // validation of the user existion
        require(_doesUserExist(_msgSender()) == true, "withdraw: the user is not active");

        _withdraw(orderId);
    }


    // -----------------------------------------
    // GETTERS
    // -----------------------------------------

    function doesUserExist(
        address user
    ) external view returns (bool) {
        return _doesUserExist(user);
    }

    function getUserActiveDeposits(
        address user,
        uint256 cursor,
        uint256 howMany
    ) public view returns (
        uint256[] memory orderIds,
        uint256[] memory amounts,
        uint256[] memory initTimestamps,
        uint256 newCursor
    ) {
        // amount of deposits which user has been done
        uint256 depositsLength = _users[user].index;
        uint256 activeOrdersLength = 0;

        // calculate lenght of necesseary array
        for (uint256 i = 0; i < depositsLength; i++){
            uint256 orderId = _users[user].orderIdByIndex[i];
            if (_users[user].orders[orderId].withdrawn == false) {
                activeOrdersLength++;
            }
        }

        uint256 length = howMany;
        if (length > activeOrdersLength - cursor) {
            length = activeOrdersLength - cursor;
        }

        // create new arrays with necesseary array lengths
        orderIds = new uint256[](length);
        amounts = new uint256[](length);
        initTimestamps = new uint256[](length);

        uint256 j = 0;
        for (uint256 i = 0; i < depositsLength; i++){
            if (j == length) {
                break;
            } else {
                uint256 orderId = _users[user].orderIdByIndex[cursor + i];
                if (_users[user].orders[orderId].withdrawn == false) {
                    orderIds[j] = orderId;
                    amounts[j] = _users[user].orders[orderId].amount;
                    initTimestamps[j] = _users[user].orders[orderId].initTimestamp;

                    j++;
                }
            }
        }

        return (
            orderIds,
            amounts,
            initTimestamps,
            cursor + length
        );
    }

    function getUserFilledDeposits(
        address user,
        uint256 cursor,
        uint256 howMany
    ) external view returns (
        uint256[] memory orderIds,
        uint256[] memory amounts,
        uint256[] memory initTimestamps,
        uint256 newCursor
    ) {
        // amount of deposits which user has been done
        uint256 depositsLength = _users[user].index;

        uint256 length = howMany;
        if (length > depositsLength - cursor) {
            length = depositsLength - cursor;
        }

        // init empty arrays which should been returned
        orderIds = new uint256[](length);
        amounts = new uint256[](length);
        initTimestamps = new uint256[](length);

        uint256 j = 0;
        for (uint256 i = 0; i < length; i++){
            uint256 orderId = _users[user].orderIdByIndex[cursor + i];
            orderIds[j] = orderId;
            amounts[j] = _users[user].orders[orderId].amount;
            initTimestamps[j] = _users[user].orders[orderId].initTimestamp;

            j++;
        }

        return (
            orderIds,
            amounts,
            initTimestamps,
            cursor + length
        );
    }

    function getUserDepositIndex(
        address user
    ) external view returns (
        uint256
    ) {
        return _users[user].index;
    }

    function getOrderDetails(
        uint256 orderId,
        address user
    ) external view returns (
        bool created,
        address asset,
        uint256 amount,
        bool withdrawn,
        uint256 initTimestamp
    ) {
        OrderDetails memory order = _getOrderDetails(orderId, user);
        return (
            order.created,
            order.asset,
            order.amount,
            order.withdrawn,
            order.initTimestamp
        );
    }

    function getUserById(
        uint256 userId
    ) external view returns (
        address user
    ) {
        return _usersById[userId];
    }

    function getUsersList(
        uint256 cursor,
        uint256 howMany
    ) external view returns (
        address[] memory users,
        uint256 newCursor
    ) {
        uint256 length = howMany;
        if (length > _usersCount - cursor) {
            length = _usersCount - cursor;
        }

        users = new address[](length);
        for (uint256 i = 0; i < length; i++) {
            users[i] = _usersById[cursor + i];
        }

        return (users, cursor + length);
    }

    function getUsersCount() external view returns (uint256 count) {
        return _usersCount;
    }

    // -----------------------------------------
    // INTERNAL
    // -----------------------------------------

    function _deposit(
        uint256 orderId,
        address sender,
        address asset,
        uint256 amount
    ) internal {
        _activateIfUserIsNew(sender);
        _depositOrderBalance(orderId, sender, asset, amount);

        // Increase user deposits count
        _users[sender].index += 1;

        // Update deposits mapping and count
        _depositsById[_depositsCount] = orderId;
        _depositsCount++;

        emit AssetDeposited(orderId, sender, asset, amount);
    }

    function _withdraw(
        uint256 orderId
    ) internal {
        // storing the order information (asset and amount)
        OrderDetails memory order = _getOrderDetails(orderId, _msgSender());
        address asset = order.asset;
        uint256 amount = order.amount;

        // validations before withdrawal
        require(amount != 0, "withdraw: order has no positive value");
        require(order.withdrawn == false, "withdraw: this order Id has been already withdrawn or waiting for the swap");

        _withdrawOrderBalance(orderId, _msgSender());

        if (asset == _ethAssetIdentificator) {
            _msgSender().transfer(amount);
        } else {
            IERC20(asset).safeTransfer(_msgSender(), amount);
        }

        emit AssetWithdrawal(orderId, _msgSender(), asset, amount);
    }

    function _activateIfUserIsNew(
        address user
    ) internal returns (bool) {
        if (_doesUserExist(user) == false) {
            _users[user].exist = true;
            _usersById[_usersCount] = user;
            _usersCount++;
        }
        return true;
    }

    function _depositOrderBalance(
        uint256 orderId,
        address user,
        address asset,
        uint256 amount
    ) internal returns (bool) {
        _users[user].orderIdByIndex[_users[user].index] = orderId;
        _users[user].orders[orderId] = OrderDetails(true, asset, amount, false, block.timestamp);
        return true;
    }

    function _reopenExistingOrder(
        uint256 orderId,
        address user
    ) internal returns (bool) {
        _users[user].orders[orderId].withdrawn = false;
        _users[user].orders[orderId].initTimestamp = block.timestamp;
        return true;
    }

    function _withdrawOrderBalance(
        uint256 orderId,
        address user
    ) internal returns (bool) {
        _users[user].orders[orderId].withdrawn = true;
        return true;
    }

    function _doesUserExist(
        address user
    ) internal view returns (bool) {
        return _users[user].exist;
    }

    function _getOrderDetails(
        uint256 orderId,
        address user
    ) internal view returns (OrderDetails memory order) {
        return _users[user].orders[orderId];
    }

}

/**
 * @title CrossBlockchainSwap
 * @dev Fully autonomous cross-blockchain swapping smart contract
 */
contract CrossBlockchainSwap is AssetsValue {
    // -----------------------------------------
    // EVENTS
    // -----------------------------------------

    event Initiated(
        uint256 indexed orderId,
        bytes32 indexed secretHash,
        address indexed initiator,
        address recipient,
        uint256 initTimestamp,
        uint256 refundTimestamp,
        address asset,
        uint256 amount
    );

    event Redeemed(
        bytes32 secretHash,
        uint256 redeemTimestamp,
        bytes32 secret,
        address indexed redeemer
    );

    event Refunded(
        uint256 orderId,
        bytes32 secretHash,
        uint256 refundTime,
        address indexed refunder
    );

    // -----------------------------------------
    // MODIFIERS
    // -----------------------------------------

    modifier swapIsNotInitiated(bytes32 secretHash) {
        require(_swaps[secretHash].state == State.Empty, "swapIsNotInitiated: this secret hash was already used, please use another one");
        _;
    }

    modifier swapIsRedeemable(bytes32 secret) {
        bool isRedeemable = _isRedeemable(secret);
        require(isRedeemable, "swapIsRedeemable: the redeem is not available");
        _;
    }

    modifier swapIsRefundable(bytes32 secretHash, address refunder) {
        bool isRefundable = _isRefundable(secretHash, refunder);
        require(isRefundable, "swapIsRefundable: refund is not available");
        _;
    }

    // -----------------------------------------
    // EXTERNAL
    // -----------------------------------------

    /**
     *  @dev If user wants to swap ERC token, before initiating the swap between that
     *  initiator need to call approve method from his tokens' smart contract,
     *  approving to it to spend the value1 amount of tokens
     *  @param secretHash the encoded secret which they discussed at offline (SHA256)
     *  @param refundTimestamp the period when the swap should be active
     *  it should be written in MINUTES
     */
    function initiate(
        uint256 orderId,
        bytes32 secretHash,
        address recipient,
        uint256 refundTimestamp
    ) public swapIsNotInitiated(secretHash) {
        require(recipient != address(0), "initiate: invalid recipient address");

        // validation that refund Timestamp more than exchange min limit and less then max limit
        _validateRefundTimestamp(refundTimestamp * 1 minutes);

        OrderDetails memory order = _getOrderDetails(orderId, _msgSender());

        // validation of the deposited order existing and non-zero amount
        require(order.created == true, "initiate: this order Id has not been created and deposited yet");
        require(order.withdrawn == false, "initiate: this order deposit has been withdrawn");
        require(order.amount != 0, "initiate: this order Id has been withdrawn, finished or waiting for the redeem");

        // withdrawing the balance of this orderId from sender deposites
        _withdrawOrderBalance(orderId, _msgSender());

        // swap asset details
        _swaps[secretHash].asset = order.asset;
        _swaps[secretHash].amount = order.amount;

        // swap status
        _swaps[secretHash].state = State.Filled;

        // swap clients
        _swaps[secretHash].initiator = _msgSender();
        _swaps[secretHash].recipient = recipient;
        _swaps[secretHash].secretHash = secretHash;
        _swaps[secretHash].orderId = orderId;

        // swap timestapms
        _swaps[secretHash].initTimestamp = block.timestamp;
        _swaps[secretHash].refundTimestamp = block.timestamp + (refundTimestamp * 1 minutes);

        // updating the initiator state
        Initiator storage initiator = _initiators[_msgSender()];
        initiator.swaps[initiator.index] = secretHash;
        initiator.index++;
        initiator.filledSwaps++;

        // Update deposits mapping and count
        _swapsById[_swapsCount] = secretHash;
        _swapsCount++;

        emit Initiated(
            orderId,
            secretHash,
            _msgSender(),
            recipient,
            block.timestamp,
            refundTimestamp,
            order.asset,
            order.amount
        );
    }

    /**
     *  @dev The participant of swap, who has the secret word and the secret hash can call this method
     *  and receive assets from contract.
     *  @param secret which both sides discussed before initialization
     */
    function redeem(
        bytes32 secret
    ) external swapIsRedeemable(secret) {
        // storing the secret hash generated from secret
        bytes32 secretHash = _hashTheSecret(secret);

        // closing the state of this swap order
        _swaps[secretHash].state = State.Redeemed;

        // storing the recipient address
        address recipient = _swaps[secretHash].recipient;

        if (_getSwapAssetType(secretHash) == SwapType.ETH) {
            // converting recipient address to payable address
            address payable payableReceiver = address(uint160(recipient));
            // transfer ETH to recipient wallet
            payableReceiver.transfer(_swaps[secretHash].amount);
        } else {
            // transfer tokens to recipient address
            IERC20(_swaps[secretHash].asset).safeTransfer(recipient, _swaps[secretHash].amount);
        }

        // saving the secret
        _swaps[secretHash].secret = secret;

        // decrease the filled swaps amount
        _initiators[_swaps[secretHash].initiator].filledSwaps--;

        emit Redeemed (
            secretHash,
            block.timestamp,
            secret,
            recipient
        );
    }

    /**
     *  @dev The initiator can get back his tokens until refundTimestamp comes,
     *  after that both sides cannot do anything with this swap
     *  @param secretHash the encoded secret which they discussed at offline (SHA256)
     */
    function refund(
        bytes32 secretHash
    ) public swapIsRefundable(secretHash, _msgSender()) {
        _swaps[secretHash].state = State.Refunded;
        _reopenExistingOrder(_swaps[secretHash].orderId,_msgSender());

        // decrease the filled swapss amount
        _initiators[_msgSender()].filledSwaps--;

        emit Refunded(
            _swaps[secretHash].orderId,
            secretHash,
            block.timestamp,
            _msgSender()
        );
    }

    /**
     *  @dev The method do 2 actions and optimize the processes
     *  It call refund and withdraw
     *  @param secretHash the encoded secret which they discussed at offline (SHA256)
     */
    function refundAndWithdraw(
        bytes32 secretHash
    ) external {
        refund(secretHash);
        uint256 orderId = _swaps[secretHash].orderId;
        _withdraw(orderId);
    }

    /**
     *  @dev The method do the same think as refundAndWithdraw, but for all expired swaps
     *  The caller should be able to refund and withdraw all own swaps and deposits
     */
    function refundAndWithdrawAll() external {
        uint256 filledSwaps = _initiators[_msgSender()].filledSwaps;

        for (uint256 i = 0; i < filledSwaps; i++) {
            bytes32 secretHash = _swaps[_initiators[_msgSender()].swaps[i]].secretHash;
            if (_isRefundable(secretHash, _msgSender())) {
                uint256 orderId = _swaps[_initiators[_msgSender()].swaps[i]].orderId;
                refund(secretHash);
                _withdraw(orderId);
            }
        }
    }

    // -----------------------------------------
    // GETTERS
    // -----------------------------------------

    /**
     *  @dev Method returns all atomic swaps for specified user with optional state filter.
     *  @param initiator the address of user
     *  @param state of required swap, represented as a Enum type with 4 options (0 - 3)
     *  @return orderIds array of order ids with required state
     */
    function getUserSwapsByState(
        address initiator,
        State state,
        uint256 cursor,
        uint256 howMany
    ) public view returns (
        uint256[] memory orderIds,
        uint256 newCursor
    ) {
        uint256 swapsLength = _initiators[initiator].index;
        uint256 filteredOrdersLength = 0;

        // calculate lenght of necesseary array
        for (uint256 i = 0; i < swapsLength; i++){
            Swap memory swap = _swaps[_initiators[initiator].swaps[i]];
            if (swap.state == state) {
                filteredOrdersLength++;
            }
        }

        uint256 length = howMany;
        if (length > filteredOrdersLength - cursor) {
            length = filteredOrdersLength - cursor;
        }

        // create new array with necesseary array lengths
        orderIds = new uint256[](length);

        // filter orderIds by requirement
        uint256 j = 0;
        for (uint256 i = 0; i < swapsLength; i++){
            if (j == length) {
                break;
            } else {
                Swap memory swap = _swaps[_initiators[initiator].swaps[cursor + i]];
                if (swap.state == state) {
                    orderIds[j] = swap.orderId;

                    j++;
                }
            }
        }

        return (
            orderIds,
            cursor + length
        );
    }

    /**
     *  @dev Get user filled swaps count
     *  @return uint256 count
     */
    function getUserFilledOrdersCount(
        address user
    ) external view returns (
        uint256 count
    ) {
        return _initiators[user].filledSwaps;
    }

    /**
     *  @dev Get filled swaps order ids and amounts
     *  @return uint256[] of order ids
     *  @return uint256[] of amounts
     *  @return uint256[] of creation id's
     */
    function getUserFilledOrders(
        address user,
        uint256 cursor,
        uint256 howMany
    ) external view returns (
        uint256[] memory orderIds,
        uint256[] memory amounts,
        uint256[] memory initTimestamps,
        uint256 newCursor
    ) {
        uint256 filledSwaps = _initiators[user].filledSwaps;

        uint256 length = howMany;
        if (length > filledSwaps - cursor) {
            length = filledSwaps - cursor;
        }

        orderIds = new uint256[](length);
        amounts = new uint256[](length);
        initTimestamps = new uint256[](length);

        uint256 j = 0;
        for(uint256 i = 0; i <= _initiators[user].index; i++){
            if (j == length) {
                break;
            } else {
                Swap memory swap = _swaps[_initiators[user].swaps[cursor + i]];
                if (swap.state == State.Filled) {
                    amounts[j] = swap.amount;
                    orderIds[j] = swap.orderId;
                    initTimestamps[j] = swap.initTimestamp;

                    j++;
                }
            }
        }

        return (
            orderIds,
            amounts,
            initTimestamps,
            cursor + length
        );
    }

    /**
     *  @dev Identification of the swap type with assets and value fields
     *  @param secretHash the encoded secret which they discussed at offline (SHA256)
     *  @return tp (type) of swap
     */
    function getSwapAssetType(
        bytes32 secretHash
    ) public view returns (SwapType tp) {
        return _getSwapAssetType(secretHash);
    }

    /**
     *  @dev Check the secret hash for existence, it can be used in UI for form validation
     *  @param secretHash the encoded secret which they discussed at offline (SHA256)
     *  @return state of this swap
     */
    function getSwapData(
        bytes32 _secretHash
    ) external view returns (
        uint256 initTimestamp,
        uint256 refundTimestamp,
        bytes32 secretHash,
        bytes32 secret,
        address initiator,
        address recipient,
        address asset,
        uint256 amount,
        State state
    ) {
        Swap memory swap = _swaps[_secretHash];
        return (
            swap.initTimestamp,
            swap.refundTimestamp,
            swap.secretHash,
            swap.secret,
            swap.initiator,
            swap.recipient,
            swap.asset,
            swap.amount,
            swap.state
        );
    }

    /**
     *  @dev Method check and return array of orderIds, which can being refunded by provided user
     *  @param user address of user
     *  @return array of uint256 orderIds
     */
    function getExpiredSwaps(
        address user
    ) public view returns (
        uint256[] memory orderIds,
        bytes32[] memory secretHashes
    ) {
        uint256 swapsLength = _initiators[user].index;
        uint256 expiredSwapsLength = 0;

        // calculate lenght of refund timestamps array
        for (uint256 i = 0; i < swapsLength; i++){
            bytes32 secretHash = _initiators[user].swaps[i];
            Swap memory swap = _swaps[secretHash];
            if (block.timestamp >= swap.refundTimestamp && swap.state == State.Filled) {
                expiredSwapsLength++;
            }
        }

        // create new array with necesseary array lengths
        orderIds = new uint256[](expiredSwapsLength);
        secretHashes = new bytes32[](expiredSwapsLength);

        // filter orderIds by refund timestamp
        uint256 j = 0;
        for (uint256 i = 0; i < swapsLength; i++){
            bytes32 secretHash = _initiators[user].swaps[i];
            Swap memory swap = _swaps[secretHash];
            if (block.timestamp >= swap.refundTimestamp && swap.state == State.Filled) {
                orderIds[j] = swap.orderId;
                secretHashes[j] = secretHash;
                j++;
            }
        }

        return (
            orderIds,
            secretHashes
        );
    }

    /**
     *  @dev To avoid issues between solidity hashing algorithm and the algorithm which will be used in the platform
     *  we gonna use the same hashing algorithm which uses the smart contract
     *  this is only the getter method without interaction from the blockchain, so it is safe
     *  @return secret hash of bytes32 secret
     */
    function getHashOfSecret(
        bytes32 secret
    ) external pure returns (bytes32) {
        return _hashTheSecret(secret);
    }

    /**
     *  @dev Get limits of a lifetime for swap in minutes
     *  @return min lifetime
     *  @return max lifetime
     */
    function getSwapLifetimeLimits() public view returns (
        uint256 min,
        uint256 max
    ) {
        return (
            _swapTimeLimits.min,
            _swapTimeLimits.max
        );
    }

    /**
     *  @dev Get the count of initiated swaps
     */
    function getSwapsCount() external view returns (
        uint256 swapsCount
    ) {
        return _swapsCount;
    }

    /**
     *  @dev Get the secretHash by provided id
     */
    function getSwapsSecretHashById(
        uint256 swapId
    ) external view returns (
        bytes32 secretHash
    ) {
        return _swapsById[swapId];
    }

    // -----------------------------------------
    // INTERNAL
    // -----------------------------------------

    /**
     *  @dev Validating the period time of swap
     * It should be equal/bigger than 10 minutes and equal/less than 180 days
     */
    function _validateRefundTimestamp(
        uint256 refundTimestamp
    ) private view {
        require(refundTimestamp >= _swapTimeLimits.min, "_validateRefundTimestamp: the timestamp should be bigger than min swap lifetime");
        require(_swapTimeLimits.max >= refundTimestamp, "_validateRefundTimestamp: the timestamp should be smaller than max swap lifetime");
    }

    function _isRefundable(
        bytes32 secretHash,
        address refunder
    ) internal view returns (bool) {
        bool isFilled = _swaps[secretHash].state == State.Filled;
        bool isCallerInitiator = _swaps[secretHash].initiator == refunder;
        uint256 refundTimestamp = _swaps[secretHash].refundTimestamp;
        bool isTimeReached = block.timestamp >= refundTimestamp;

        return isFilled && isCallerInitiator && isTimeReached;
    }

    function _isRedeemable(
        bytes32 secret
    ) internal view returns (bool) {
        bytes32 secretHash = _hashTheSecret(secret);
        bool isSwapFilled = _swaps[secretHash].state == State.Filled;
        uint256 refundTimestamp = _swaps[secretHash].refundTimestamp;
        bool isSwapActive = refundTimestamp > block.timestamp;

        return isSwapFilled && isSwapActive;
    }

    function _hashTheSecret(
        bytes32 secret
    ) private pure returns (bytes32) {
        return sha256(abi.encodePacked(secret));
    }

    function _getSwapAssetType(
        bytes32 secretHash
    ) private view returns (SwapType tp) {
        if (_swaps[secretHash].asset == _ethAssetIdentificator) {
            return SwapType.ETH;
        } else {
            return SwapType.Token;
        }
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_logic","type":"address"},{"internalType":"address","name":"_admin","type":"address"}],"payable":true,"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":true,"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newMin","type":"uint256"},{"internalType":"uint256","name":"newMax","type":"uint256"}],"name":"changeSwapLifetimeLimits","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"string","name":"newVersion","type":"string"}],"name":"upgradeTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"string","name":"newVersion","type":"string"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]

600480546001600160a01b031916905560c06040819052610258608081905262ed4e0060a0819052600b91909155600c5562000fd038819003908190833981810160405260408110156200005257600080fd5b508051602090910151816200006f6001600160e01b036200019716565b600080546001600160a01b0319166001600160a01b03928316178082556040519216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a360405180602362000f72823960405190819003602301902060008051602062000f52833981519152149050620000e957fe5b62000130816040518060400160405280600581526020017f312e302e300000000000000000000000000000000000000000000000000000008152506200019c60201b60201c565b50604080517f6f72672e7a657070656c696e6f732e70726f78792e61646d696e0000000000008152905190819003601a01902060008051602062000f32833981519152146200017b57fe5b6200018f816001600160e01b036200023c16565b5050620002f7565b335b90565b620001bb826001600160a01b03166200024f60201b62000a311760201c565b62000212576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b81526020018062000f95603b913960400191505060405180910390fd5b80516200022790600d90602084019062000255565b505060008051602062000f5283398151915255565b60008051602062000f3283398151915255565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200029857805160ff1916838001178555620002c8565b82800160010185558215620002c8579182015b82811115620002c8578251825591602001919060010190620002ab565b50620002d6929150620002da565b5090565b6200019991905b80821115620002d65760008155600101620002e1565b610c2b80620003076000396000f3fe60806040526004361061009c5760003560e01c80638f283970116100645780638f283970146102185780638f32d59b1461024b578063a4cdbd1414610274578063d7e24337146102a4578063f2fde38b14610376578063f851a440146103a95761009c565b806336ba9794146100a657806354fd4d50146101335780635c60da1b146101bd578063715018a6146101ee5780638da5cb5b14610203575b6100a46103be565b005b3480156100b257600080fd5b506100a4600480360360408110156100c957600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100f457600080fd5b82018360208201111561010657600080fd5b8035906020019184600183028401116401000000008311171561012857600080fd5b5090925090506103d8565b34801561013f57600080fd5b5061014861044b565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561018257818101518382015260200161016a565b50505050905090810190601f1680156101af5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101c957600080fd5b506101d26104e2565b604080516001600160a01b039092168252519081900360200190f35b3480156101fa57600080fd5b506100a46104f1565b34801561020f57600080fd5b506101d261054c565b34801561022457600080fd5b506100a46004803603602081101561023b57600080fd5b50356001600160a01b031661055b565b34801561025757600080fd5b50610260610625565b604080519115158252519081900360200190f35b34801561028057600080fd5b506100a46004803603604081101561029757600080fd5b5080359060200135610649565b6100a4600480360360608110156102ba57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156102e557600080fd5b8201836020820111156102f757600080fd5b8035906020019184600183028401116401000000008311171561031957600080fd5b91939092909160208101903564010000000081111561033757600080fd5b82018360208201111561034957600080fd5b8035906020019184600183028401116401000000008311171561036b57600080fd5b5090925090506106fb565b34801561038257600080fd5b506100a46004803603602081101561039957600080fd5b50356001600160a01b03166107e1565b3480156103b557600080fd5b506101d26107fb565b6103c6610805565b6103d66103d1610865565b61088a565b565b6103e06108ae565b6001600160a01b0316336001600160a01b0316141561043e576104398383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506108d392505050565b610446565b6104466103be565b505050565b600d8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104d75780601f106104ac576101008083540402835291602001916104d7565b820191906000526020600020905b8154815290600101906020018083116104ba57829003601f168201915b505050505090505b90565b60006104ec610865565b905090565b6104f9610625565b61050257600080fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031690565b6105636108ae565b6001600160a01b0316336001600160a01b0316141561061a576001600160a01b0381166105c15760405162461bcd60e51b8152600401808060200182810382526036815260200180610b026036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6105ea6108ae565b604080516001600160a01b03928316815291841660208301528051918290030190a161061581610915565b610622565b6106226103be565b50565b600080546001600160a01b031661063a610939565b6001600160a01b031614905090565b610651610625565b61065a57600080fd5b816106965760405162461bcd60e51b8152600401808060200182810382526043815260200180610b386043913960600191505060405180910390fd5b818110156106d55760405162461bcd60e51b8152600401808060200182810382526041815260200180610bb66041913960600191505060405180910390fd5b60408051808201909152603c928302808252919092026020909201829052600b55600c55565b6107036108ae565b6001600160a01b0316336001600160a01b031614156107d25761075c8585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506108d392505050565b6000856001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d80600081146107b9576040519150601f19603f3d011682016040523d82523d6000602084013e6107be565b606091505b50509050806107cc57600080fd5b506107da565b6107da6103be565b5050505050565b6107e9610625565b6107f257600080fd5b6106228161093d565b60006104ec6108ae565b61080d6108ae565b6001600160a01b0316336001600160a01b0316141561085d5760405162461bcd60e51b8152600401808060200182810382526032815260200180610ad06032913960400191505060405180910390fd5b6103d66103d6565b7f7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c35490565b3660008037600080366000845af43d6000803e8080156108a9573d6000f35b3d6000fd5b7f10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b5490565b6108dd82826109ab565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b7f10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b55565b3390565b6001600160a01b03811661095057600080fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6109bd826001600160a01b0316610a31565b6109f85760405162461bcd60e51b815260040180806020018281038252603b815260200180610b7b603b913960400191505060405180910390fd5b8051610a0b90600d906020840190610a37565b50507f7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c355565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610a7857805160ff1916838001178555610aa5565b82800160010185558215610aa5579182015b82811115610aa5578251825591602001919060010190610a8a565b50610ab1929150610ab5565b5090565b6104df91905b80821115610ab15760008155600101610abb56fe43616e6e6f742063616c6c2066616c6c6261636b2066756e6374696f6e2066726f6d207468652070726f78792061646d696e43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f20616464726573736368616e6765537761704c69666574696d654c696d6974733a206e65774d696e20616e64206e65774d61782073686f756c6420626520626967676572207468656e203043616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e747261637420616464726573736368616e6765537761704c69666574696d654c696d6974733a20746865206e65774d61782073686f756c6420626520626967676572207468656e206e65774d6178a265627a7a72315820843eae6f470e00ecfd07082b9bfe0eb5c50392ea0845c59834fcb048d3306ca064736f6c634300050c003210d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c36f72672e7a657070656c696e6f732e70726f78792e696d706c656d656e746174696f6e43616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373000000000000000000000000c6304e326b2462f59d811285eab0d5a50266f362000000000000000000000000fc93512d1848fa37f40d7782ffc291617c0e5615

Deployed Bytecode

0x60806040526004361061009c5760003560e01c80638f283970116100645780638f283970146102185780638f32d59b1461024b578063a4cdbd1414610274578063d7e24337146102a4578063f2fde38b14610376578063f851a440146103a95761009c565b806336ba9794146100a657806354fd4d50146101335780635c60da1b146101bd578063715018a6146101ee5780638da5cb5b14610203575b6100a46103be565b005b3480156100b257600080fd5b506100a4600480360360408110156100c957600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100f457600080fd5b82018360208201111561010657600080fd5b8035906020019184600183028401116401000000008311171561012857600080fd5b5090925090506103d8565b34801561013f57600080fd5b5061014861044b565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561018257818101518382015260200161016a565b50505050905090810190601f1680156101af5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101c957600080fd5b506101d26104e2565b604080516001600160a01b039092168252519081900360200190f35b3480156101fa57600080fd5b506100a46104f1565b34801561020f57600080fd5b506101d261054c565b34801561022457600080fd5b506100a46004803603602081101561023b57600080fd5b50356001600160a01b031661055b565b34801561025757600080fd5b50610260610625565b604080519115158252519081900360200190f35b34801561028057600080fd5b506100a46004803603604081101561029757600080fd5b5080359060200135610649565b6100a4600480360360608110156102ba57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156102e557600080fd5b8201836020820111156102f757600080fd5b8035906020019184600183028401116401000000008311171561031957600080fd5b91939092909160208101903564010000000081111561033757600080fd5b82018360208201111561034957600080fd5b8035906020019184600183028401116401000000008311171561036b57600080fd5b5090925090506106fb565b34801561038257600080fd5b506100a46004803603602081101561039957600080fd5b50356001600160a01b03166107e1565b3480156103b557600080fd5b506101d26107fb565b6103c6610805565b6103d66103d1610865565b61088a565b565b6103e06108ae565b6001600160a01b0316336001600160a01b0316141561043e576104398383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506108d392505050565b610446565b6104466103be565b505050565b600d8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104d75780601f106104ac576101008083540402835291602001916104d7565b820191906000526020600020905b8154815290600101906020018083116104ba57829003601f168201915b505050505090505b90565b60006104ec610865565b905090565b6104f9610625565b61050257600080fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031690565b6105636108ae565b6001600160a01b0316336001600160a01b0316141561061a576001600160a01b0381166105c15760405162461bcd60e51b8152600401808060200182810382526036815260200180610b026036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6105ea6108ae565b604080516001600160a01b03928316815291841660208301528051918290030190a161061581610915565b610622565b6106226103be565b50565b600080546001600160a01b031661063a610939565b6001600160a01b031614905090565b610651610625565b61065a57600080fd5b816106965760405162461bcd60e51b8152600401808060200182810382526043815260200180610b386043913960600191505060405180910390fd5b818110156106d55760405162461bcd60e51b8152600401808060200182810382526041815260200180610bb66041913960600191505060405180910390fd5b60408051808201909152603c928302808252919092026020909201829052600b55600c55565b6107036108ae565b6001600160a01b0316336001600160a01b031614156107d25761075c8585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506108d392505050565b6000856001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d80600081146107b9576040519150601f19603f3d011682016040523d82523d6000602084013e6107be565b606091505b50509050806107cc57600080fd5b506107da565b6107da6103be565b5050505050565b6107e9610625565b6107f257600080fd5b6106228161093d565b60006104ec6108ae565b61080d6108ae565b6001600160a01b0316336001600160a01b0316141561085d5760405162461bcd60e51b8152600401808060200182810382526032815260200180610ad06032913960400191505060405180910390fd5b6103d66103d6565b7f7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c35490565b3660008037600080366000845af43d6000803e8080156108a9573d6000f35b3d6000fd5b7f10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b5490565b6108dd82826109ab565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b7f10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b55565b3390565b6001600160a01b03811661095057600080fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6109bd826001600160a01b0316610a31565b6109f85760405162461bcd60e51b815260040180806020018281038252603b815260200180610b7b603b913960400191505060405180910390fd5b8051610a0b90600d906020840190610a37565b50507f7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c355565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610a7857805160ff1916838001178555610aa5565b82800160010185558215610aa5579182015b82811115610aa5578251825591602001919060010190610a8a565b50610ab1929150610ab5565b5090565b6104df91905b80821115610ab15760008155600101610abb56fe43616e6e6f742063616c6c2066616c6c6261636b2066756e6374696f6e2066726f6d207468652070726f78792061646d696e43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f20616464726573736368616e6765537761704c69666574696d654c696d6974733a206e65774d696e20616e64206e65774d61782073686f756c6420626520626967676572207468656e203043616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e747261637420616464726573736368616e6765537761704c69666574696d654c696d6974733a20746865206e65774d61782073686f756c6420626520626967676572207468656e206e65774d6178a265627a7a72315820843eae6f470e00ecfd07082b9bfe0eb5c50392ea0845c59834fcb048d3306ca064736f6c634300050c0032

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000c6304e326b2462f59d811285eab0d5a50266f362000000000000000000000000fc93512d1848fa37f40d7782ffc291617c0e5615

-----Decoded View---------------
Arg [0] : _logic (address): 0xC6304e326B2462f59D811285EaB0d5a50266f362
Arg [1] : _admin (address): 0xFc93512D1848fA37F40D7782ffC291617c0e5615

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000c6304e326b2462f59d811285eab0d5a50266f362
Arg [1] : 000000000000000000000000fc93512d1848fa37f40d7782ffc291617c0e5615


Deployed Bytecode Sourcemap

22757:426:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14516:11;:9;:11::i;:::-;22757:426;20952:142;;8:9:-1;5:2;;;30:1;27;20:12;5:2;20952:142:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;20952:142:0;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;20952:142:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;20952:142:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;20952:142:0;;-1:-1:-1;20952:142:0;-1:-1:-1;20952:142:0;:::i;20086:82::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;20086:82:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;20086:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20233:92;;8:9:-1;5:2;;;30:1;27;20:12;5:2;20233:92:0;;;:::i;:::-;;;;-1:-1:-1;;;;;20233:92:0;;;;;;;;;;;;;;9520:140;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9520:140:0;;;:::i;8728:79::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;8728:79:0;;;:::i;20502:221::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;20502:221:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;20502:221:0;-1:-1:-1;;;;;20502:221:0;;:::i;9063:94::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9063:94:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;13647:410;;8:9:-1;5:2;;;30:1;27;20:12;5:2;13647:410:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13647:410:0;;;;;;;:::i;21656:258::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;21656:258:0;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;21656:258:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;21656:258:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;21656:258:0;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;21656:258:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;21656:258:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;21656:258:0;;-1:-1:-1;21656:258:0;-1:-1:-1;21656:258:0;:::i;9837:109::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9837:109:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;9837:109:0;-1:-1:-1;;;;;9837:109:0;;:::i;19952:74::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;19952:74:0;;;:::i;14628:88::-;14663:15;:13;:15::i;:::-;14683:28;14693:17;:15;:17::i;:::-;14683:9;:28::i;:::-;14628:88::o;20952:142::-;19828:8;:6;:8::i;:::-;-1:-1:-1;;;;;19814:22:0;:10;-1:-1:-1;;;;;19814:22:0;;19810:76;;;21048:41;21059:17;21078:10;;21048:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;21048:10:0;;-1:-1:-1;;;21048:41:0:i;:::-;19810:76;;;19869:11;:9;:11::i;:::-;20952:142;;;:::o;20086:82::-;20155:8;20148:15;;;;;;;;-1:-1:-1;;20148:15:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20128:13;;20148:15;;20155:8;;20148:15;;20155:8;20148:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20086:82;;:::o;20233:92::-;20282:7;20303:17;:15;:17::i;:::-;20296:24;;20233:92;:::o;9520:140::-;8940:9;:7;:9::i;:::-;8932:18;;;;;;9619:1;9603:6;;9582:40;;-1:-1:-1;;;;;9603:6:0;;;;9582:40;;9619:1;;9582:40;9650:1;9633:19;;-1:-1:-1;;;;;;9633:19:0;;;9520:140::o;8728:79::-;8766:7;8793:6;-1:-1:-1;;;;;8793:6:0;8728:79;:::o;20502:221::-;19828:8;:6;:8::i;:::-;-1:-1:-1;;;;;19814:22:0;:10;-1:-1:-1;;;;;19814:22:0;;19810:76;;;-1:-1:-1;;;;;20571:22:0;;20563:89;;;;-1:-1:-1;;;20563:89:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20662:32;20675:8;:6;:8::i;:::-;20662:32;;;-1:-1:-1;;;;;20662:32:0;;;;;;;;;;;;;;;;;;;;;20699:19;20709:8;20699:9;:19::i;:::-;19810:76;;;19869:11;:9;:11::i;:::-;20502:221;:::o;9063:94::-;9103:4;9143:6;;-1:-1:-1;;;;;9143:6:0;9127:12;:10;:12::i;:::-;-1:-1:-1;;;;;9127:22:0;;9120:29;;9063:94;:::o;13647:410::-;8940:9;:7;:9::i;:::-;8932:18;;;;;;13776:11;13768:91;;;;-1:-1:-1;;;13768:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13888:6;13878;:16;;13870:94;;;;-1:-1:-1;;;13870:94:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13995:54;;;;;;;;;14019:9;14010:18;;;13995:54;;;14030:18;;;;13995:54;;;;;;;13977:15;:72;;;13647:410::o;21656:258::-;19828:8;:6;:8::i;:::-;-1:-1:-1;;;;;19814:22:0;:10;-1:-1:-1;;;;;19814:22:0;;19810:76;;;21788:41;21799:17;21818:10;;21788:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;21788:10:0;;-1:-1:-1;;;21788:41:0:i;:::-;21835:12;21852:17;-1:-1:-1;;;;;21852:30:0;21883:4;;21852:36;;;;;30:3:-1;22:6;14;1:33;21852:36:0;;45:16:-1;;;-1:-1;21852:36:0;;-1:-1:-1;21852:36:0;;-1:-1:-1;;21852:36:0;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;21834:54:0;;;21901:7;21893:16;;;;;;19847:1;19810:76;;;19869:11;:9;:11::i;:::-;21656:258;;;;;:::o;9837:109::-;8940:9;:7;:9::i;:::-;8932:18;;;;;;9910:28;9929:8;9910:18;:28::i;19952:74::-;19992:7;20013:8;:6;:8::i;22416:155::-;22477:8;:6;:8::i;:::-;-1:-1:-1;;;;;22463:22:0;:10;-1:-1:-1;;;;;22463:22:0;;;22455:85;;;;-1:-1:-1;;;22455:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22545:21;:19;:21::i;17098:154::-;16736:66;17232:11;;17215:33::o;15249:708::-;15542:12;15539:1;15536;15523:32;15727:1;15724;15710:12;15707:1;15691:14;15686:3;15673:56;15788:14;15785:1;15782;15767:36;15817:6;15868:36;;;;15929:14;15926:1;15919:25;15868:36;15887:14;15884:1;15877:25;21960:134;19527:66;22074:11;;22058:32::o;17432:180::-;17519:49;17538:17;17557:10;17519:18;:49::i;:::-;17580:27;;-1:-1:-1;;;;;17580:27:0;;;;;;;;17432:180;;:::o;22211:129::-;19527:66;22309:22;22303:33::o;3793:98::-;3873:10;3793:98;:::o;10096:187::-;-1:-1:-1;;;;;10170:22:0;;10162:31;;;;;;10230:6;;;10209:38;;-1:-1:-1;;;;;10209:38:0;;;;10230:6;;;10209:38;;;10258:6;:17;;-1:-1:-1;;;;;;10258:17:0;-1:-1:-1;;;;;10258:17:0;;;;;;;;;;10096:187::o;17794:332::-;17897:30;:17;-1:-1:-1;;;;;17897:28:0;;:30::i;:::-;17889:102;;;;-1:-1:-1;;;17889:102:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17999:21;;;;:8;;:21;;;;;:::i;:::-;-1:-1:-1;;16736:66:0;18086:31;18077:45::o;2379:627::-;2951:20;2990:8;;;2379:627::o;22757:426::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;22757:426:0;;;-1:-1:-1;22757:426:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;

Swarm Source

bzzr://843eae6f470e00ecfd07082b9bfe0eb5c50392ea0845c59834fcb048d3306ca0

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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.