Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 932 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Claim | 19238965 | 189 days ago | IN | 0 ETH | 0.00242987 | ||||
Deposit | 19011721 | 221 days ago | IN | 0.0015 ETH | 0.00185257 | ||||
Deposit | 18762938 | 256 days ago | IN | 0.0015 ETH | 0.00326657 | ||||
Deposit | 18705612 | 264 days ago | IN | 0.0015 ETH | 0.00285199 | ||||
Claim | 17961283 | 368 days ago | IN | 0 ETH | 0.00131455 | ||||
Claim | 17402617 | 447 days ago | IN | 0 ETH | 0.00235701 | ||||
Claim | 17245516 | 469 days ago | IN | 0 ETH | 0.00784347 | ||||
Deposit | 17151004 | 482 days ago | IN | 0.0015 ETH | 0.00354046 | ||||
Deposit | 17089277 | 491 days ago | IN | 0.0015 ETH | 0.00581108 | ||||
Claim | 16871304 | 522 days ago | IN | 0 ETH | 0.00374984 | ||||
Claim | 16834865 | 527 days ago | IN | 0 ETH | 0.00499618 | ||||
Deposit | 16824618 | 528 days ago | IN | 0.0015 ETH | 0.00220163 | ||||
Deposit | 16824605 | 528 days ago | IN | 0.0015 ETH | 0.00231692 | ||||
Claim | 16710408 | 544 days ago | IN | 0 ETH | 0.00189532 | ||||
Deposit | 16671220 | 550 days ago | IN | 0.0015 ETH | 0.00443561 | ||||
Claim | 16656264 | 552 days ago | IN | 0 ETH | 0.00292585 | ||||
Claim | 16654614 | 552 days ago | IN | 0 ETH | 0.00315661 | ||||
Claim | 16650868 | 553 days ago | IN | 0 ETH | 0.00684849 | ||||
Claim | 16649285 | 553 days ago | IN | 0 ETH | 0.0040112 | ||||
Claim | 16636148 | 555 days ago | IN | 0 ETH | 0.00491941 | ||||
Deposit | 16191943 | 617 days ago | IN | 0.0015 ETH | 0.00240068 | ||||
Deposit | 16177570 | 619 days ago | IN | 0.0015 ETH | 0.00237991 | ||||
Deposit | 16177264 | 619 days ago | IN | 0.0015 ETH | 0.00312631 | ||||
Deposit | 16090456 | 631 days ago | IN | 0.0015 ETH | 0.00132714 | ||||
Claim | 16023868 | 640 days ago | IN | 0 ETH | 0.00032254 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
19011721 | 221 days ago | 0.0015 ETH | ||||
18762938 | 256 days ago | 0.0015 ETH | ||||
18705612 | 264 days ago | 0.0015 ETH | ||||
17151004 | 482 days ago | 0.0015 ETH | ||||
17089277 | 491 days ago | 0.0015 ETH | ||||
16824618 | 528 days ago | 0.0015 ETH | ||||
16824605 | 528 days ago | 0.0015 ETH | ||||
16671220 | 550 days ago | 0.0015 ETH | ||||
16191943 | 617 days ago | 0.0015 ETH | ||||
16177570 | 619 days ago | 0.0015 ETH | ||||
16177264 | 619 days ago | 0.0015 ETH | ||||
16090456 | 631 days ago | 0.0015 ETH | ||||
15795793 | 672 days ago | 0.0015 ETH | ||||
15732393 | 681 days ago | 0.0015 ETH | ||||
15730431 | 681 days ago | 0.0015 ETH | ||||
15727871 | 682 days ago | 0.0015 ETH | ||||
15727750 | 682 days ago | 0.0015 ETH | ||||
15726519 | 682 days ago | 0.0015 ETH | ||||
15725742 | 682 days ago | 0.0015 ETH | ||||
15725581 | 682 days ago | 0.0015 ETH | ||||
15725284 | 682 days ago | 0.0015 ETH | ||||
15723861 | 682 days ago | 0.0015 ETH | ||||
15719401 | 683 days ago | 0.0015 ETH | ||||
15712440 | 684 days ago | 0.0015 ETH | ||||
15711310 | 684 days ago | 0.0015 ETH |
Loading...
Loading
Contract Name:
ETHBridgeAgent
Compiler Version
v0.8.4+commit.c7e474f2
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./AbstractBridgeAgent.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; /** * @title ETH implementation of the bridge agent * * The implementation of this agent is as follows: * 1. Token Owner registers a token with this agent (register()) * 2. Token User deposits a token amount X to the agent contract (deposit()) * 3. [off chain] Token User claims a token amount X in another chain * 4. [off chain] Token User deposits a token amount Y in another chain * 5. Token User claims a token amount Y and the balance is being transferred * from the agent back to user (claim()) * * See {AbstractBridgeAgent} documentation for some core concepts description. */ contract ETHBridgeAgent is AbstractBridgeAgent { using SafeERC20 for IERC20; using ECDSA for bytes32; /** * @dev Initializes the agent */ constructor(address _bridgeSigner, address payable _treasurer) AbstractBridgeAgent(_bridgeSigner, _treasurer) // solhint-disable-next-line no-empty-blocks { } /** * @dev Deposits a given amount of token that can be claimed in another chain. * * @param toChain target chain ID where the token amount will be claimed * @param token address of a registered token to be deposited * @param toWallet caller address that will claim the token from the {toChain} * @param amount wei amount of token to be deposited/claimed * @param bridgeSig signature issued by the Bridge Service * @param sigExpire nonce/expiration issued by the Bridge Service * * This function is payable(), receiving service fee in the form of ether. * The actual fee value is obtained from the Bridge Service along with {bridgeSig} * and {sigExpire}. * * In this ETH-specific implementation, the agent transfers a given amount of * token from a user to itself (agent). The amount is withhold until the user * comes back from the subchain to claim it back. * * The Bridge Service monitors the chain and issue bridge/token signatures * once the deposit transaction gets enough confirmations. The two signatures * can later be obtained from the Bridge Service and used to claim the * token amount in another chain. * * Requirements: * - Agent must not be paused. * - {token} must be registered in this agent. * - {token} must not be paused. * - {bridgeSig} cannot be reused and {sigExpire} must be after the current block time. * - Caller should have enough {token} balance to afford the deposited {amount}. */ function deposit( uint256 toChain, address token, address toWallet, uint256 amount, bytes memory bridgeSig, uint256 sigExpire ) external payable override useSignature(bridgeSig, sigExpire) whenNotPaused { require(!tokenPaused[token], "token is paused"); require(tokenSigners[token] != address(0), "token not registered"); // check signature bytes32 messageHash = keccak256( abi.encode( address(this), toChain, token, toWallet, amount, msg.value, sigExpire ) ); bytes32 ethHash = messageHash.toEthSignedMessageHash(); require( ethHash.recover(bridgeSig) == bridgeSigner, "invalid bridge signature" ); // Deposit the amount of token frmo user to the agent contract IERC20(token).safeTransferFrom(_msgSender(), address(this), amount); // User pays fee to the bridge if (msg.value > 0) { treasurer.transfer(msg.value); } emit Deposit(toChain, token, _msgSender(), toWallet, amount, msg.value); } /** * @dev Transfers a given amount of token from agent to a user * * @param depositTx deposit transaction hash from another chain * @param token address of the local token to be claimed * @param amount wei amount of token to be claimed * @param tokenSig signature of the Token Owner (obtained via Bridge Service) * @param bridgeSig signature of the Bridge Service * * Once the deposit is done in another chain and the Bridge Service has * issued token/bridge signature pair, the user can claim their token * in this chain, by calling this function. * * This ETH-specific implementation transfers the withhold amount from the * agent contract back to a user. * * Requirements: * - Agent must not be paused. * - {token} must be registered in this agent. * - {token} must not be paused. * - Caller should be the wallet that was specified in {toWallet} during {deposit()} * - Valid {tokenSig} and {bridgeSig} obtained from the Bridge Service */ function claim( bytes32 depositTx, address token, uint256 amount, bytes memory tokenSig, bytes memory bridgeSig ) external override useSignature(tokenSig, 0) useSignature(bridgeSig, 0) whenNotPaused { require(!tokenPaused[token], "token is paused"); require(tokenSigners[token] != address(0), "token not registered"); // check signature { bytes32 messageHash = keccak256( abi.encode( address(this), depositTx, token, block.chainid, _msgSender(), amount ) ); bytes32 ethHash = messageHash.toEthSignedMessageHash(); require( ethHash.recover(tokenSig) == tokenSigners[token], "invalid token signature" ); require( ethHash.recover(bridgeSig) == bridgeSigner, "invalid bridge signature" ); } // Transfer the withhold amount of token back to a user IERC20(token).safeTransfer(_msgSender(), amount); emit Claim(depositTx, token, _msgSender(), amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor () { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @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 IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { 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)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ 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' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _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) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - 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 not be false). * @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. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.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 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. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { // Check the signature length if (signature.length != 65) { revert("ECDSA: invalid signature length"); } // Divide the signature in r, s and v variables bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. // solhint-disable-next-line no-inline-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return recover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value"); require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value"); // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); require(signer != address(0), "ECDSA: invalid signature"); return signer; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; /** * @title Base implementation of the Bridge Agent * * Chain-specific Bridge Agents are meant to extend from this class * and also implement deposit() and claim() functions. * * Besides maximizing code reuse, bridge agents from different chains also * implement the same interface. The Bridge Backend uses the ABI of this class * to read agent data from blockchain, without relying on chain-specific * implementation details of agents. */ abstract contract AbstractBridgeAgent is Ownable, Pausable { using SafeERC20 for IERC20; using ECDSA for bytes32; // Each new release of bridge agent would have a new version uint8 public constant VERSION = 1; // Public key of signer that is used to sign bridge operations address public bridgeSigner; // Wallet where the bridge fee will be transferred address payable public treasurer; // Map that holds current token registrations, tokenSigners[token] = signer mapping(address => address) public tokenSigners; // Stores the list of paused tokens mapping(address => bool) public tokenPaused; // Remembers used signatures to avoid reuse and re-entry mapping(bytes32 => bool) internal signatureUsed; // Emitted when bridge signer is changed event SetBridgeSigner( address indexed previousBridgeSigner, address indexed newBridgeSigner ); // Emitted when treasurer is changed event SetTreasurer( address payable indexed previousTreasurer, address payable indexed newTreasurer ); // Emitted when a new token is registered or existing registration is updated event Register( address indexed token, address indexed baseToken, address indexed signer ); // Emitted when amount of registered token is deposited event Deposit( uint256 toChain, address indexed token, address indexed fromWallet, address indexed toWallet, uint256 amount, uint256 fee ); // Emitted when amount of registered token is claimed event Claim( bytes32 indexed depositTx, address indexed token, address indexed toWallet, uint256 amount ); // Emitted when a token is migrated to a new agent contract version event Migrate( address indexed token, address indexed newAgent, uint256 balance ); // Emitted when token is paused for this agent event TokenPaused(address indexed token, address indexed account); // Emitted when token is unpaused for this agent event TokenUnpaused(address indexed token, address indexed account); /** * @dev Initializes the agent * @param _bridgeSigner Public key of signer that is used to sign bridge operations * @param _treasurer Wallet where the bridge fee will be transferred */ constructor(address _bridgeSigner, address payable _treasurer) Ownable() { setBridgeSigner(_bridgeSigner); setTreasurer(_treasurer); } /** * @notice Pauses the whole agent * All user-facing operations are not be possible while the agent is paused. * * Emits {Paused()} * * Requirements: * - The agent should not be paused * - Can only be called by the brigde agent owner */ function pause() external onlyOwner { _pause(); } /** * @notice Unpauses the agent * * Emits {Unpaused()} * * Requirements: * - The agent should be paused * - Can only be called by the brigde agent owner */ function unpause() external onlyOwner { _unpause(); } /** * @notice Pauses a token * * @param token token to be paused * * Emits {TokenPaused()} * * No user-facing operations are available on a token when it's paused. * The token also gets paused when it's being migrated to a newer version * agent contract, see migrate(). * * Requirements: * - A token should not be currently paused * - A token _doesn't_ have to be registered to be paused * - Can only be called by the brigde agent owner */ function pauseToken(address token) external onlyOwner { _pauseToken(token); } /** * @notice Unpauses a token * * @param token token to be unpaused * * Emits {TokenUnpaused()} * * Requirements: * - A token should be paused * - Can only be called by the brigde agent owner */ function unpauseToken(address token) external onlyOwner { _unpauseToken(token); } /** * @dev Pauses a token – internal calls only */ function _pauseToken(address token) internal { require(!tokenPaused[token], "token is already paused"); tokenPaused[token] = true; emit TokenPaused(token, msg.sender); } /** * @dev Unpauses a token – internal calls only */ function _unpauseToken(address token) internal { require(tokenPaused[token], "token is not paused"); tokenPaused[token] = false; emit TokenUnpaused(token, msg.sender); } /** * @notice Sets a new bridge signer * * @param newBrigdeSigner Public key of signer that is used to sign bridge operations * * Emits {SetBridgeSigner()} * * Requirements: * - Can only be called by the brigde agent owner */ function setBridgeSigner(address newBrigdeSigner) public onlyOwner { require(newBrigdeSigner != address(0), "empty bridge signer"); emit SetBridgeSigner(bridgeSigner, newBrigdeSigner); bridgeSigner = newBrigdeSigner; } /** * @notice Sets a new bridge treasurer * * @param newTreasurer Wallet where the bridge fee will be transferred * * Emits {SetTreasurer()} * * Requirements: * - Can only be called by the brigde agent owner */ function setTreasurer(address payable newTreasurer) public onlyOwner { require(newTreasurer != address(0), "empty treasurer"); emit SetTreasurer(treasurer, newTreasurer); treasurer = newTreasurer; } /** * @dev Used to prevent signature reuse, re-entry, and check it's not expired * * @param sig signature * @param sigExpire timestamp in milliseconds * * This modifier reverts if a signature is reused or expired */ modifier useSignature(bytes memory sig, uint256 sigExpire) { bytes32 sigHash = keccak256(sig); require(!signatureUsed[sigHash], "reused signature"); signatureUsed[sigHash] = true; if (sigExpire > 0) { // sigExpire is in millis require(sigExpire > block.timestamp * 1000, "expired signature"); } _; } /** * @notice Registers a token in this agent. * * @param token address of a token to be registered * @param baseToken address of a token in the main chain * @param signer public key of a signer owned by token owner to sign token operations * @param bridgeSig signature issued by the Bridge Service * @param sigExpire nonce/expiration issued by the Bridge Service * * Emits {Register()} * * Prior to cross-chain transfer opertaions been made, a token needs to be * registered in the agent, presumably by its owner. It cannot be called directly * by anyone though. The Bridge Service validates token ownership and issues * a signature {bridgeSig} that allows registration. * * This function can also be used to "re-register" a token that is already * registered. This can be needed in two cases: * 1. To set a new {signer} for a token. * 2. To unregister a token. For this, pass address(0) as a {signer}. * * This function is payable(), receiving service fee in the form of ether. * The actual fee value is obtained from the Bridge Service along with {bridgeSig} * and {sigExpire}. * * NOTE: In the main chain (ETH) the {baseToken} parameter should have the * same value as {token}. This parameter is needed for sub-chains like BSC * so that the Bridge Service can index Register events and make proper routing * for the users. * * Requirements: * - Agent must not be paused. * - {token} must not be paused. * - {token} and {baseToken} cannot be empty addresses. * - {bridgeSig} cannot be reused and {sigExpire} must be after the current block time. */ function register( address token, address baseToken, address signer, bytes memory bridgeSig, uint256 sigExpire ) external payable useSignature(bridgeSig, sigExpire) whenNotPaused { require(token != address(0), "token is empty"); require(baseToken != address(0), "baseToken is empty"); require(!tokenPaused[token], "token is paused"); // Check signature { bytes32 messageHash = keccak256( abi.encode( address(this), _msgSender(), token, baseToken, signer, msg.value, sigExpire ) ); bytes32 ethHash = messageHash.toEthSignedMessageHash(); require( ethHash.recover(bridgeSig) == bridgeSigner, "invalid bridge signature" ); } tokenSigners[token] = signer; // User pays fee to the bridge if (msg.value > 0) { treasurer.transfer(msg.value); } emit Register(token, baseToken, signer); } /** * @notice Migrates a token to another agent contract * * @param token registered token to be migrated * @param newAgent address of a new agent to transfer balance to * @param tokenSig signature issued by a token owner * @param bridgeSig signature issued by the Bridge Service * @param sigExpire nonce/expiration issued by the Bridge Service * * Emits {Migrate()} * * This function is mostly needed when a new agent contract version is released. * The token owner is responsible to call this function before registering a * token {register()} on a new agent. * * Any token balance holded by this agent will be transferred to {newAgent}. * Note that there is balance only in the ETH chain – in other subchains the balance * is holded by the represented {SubchainToken}. * * Requirements: * - Agent must not be paused. * - {token} must be registered in this agent. * - {token} must not be paused. * - {tokenSig} and {bridgeSig} cannot be reused. * - {sigExpire} must be after the current block time. */ function migrate( address token, address newAgent, bytes memory tokenSig, bytes memory bridgeSig, uint256 sigExpire ) external useSignature(tokenSig, sigExpire) useSignature(bridgeSig, sigExpire) whenNotPaused { require(!tokenPaused[token], "token is paused"); require(tokenSigners[token] != address(0), "token not registered"); // check signature { bytes32 messageHash = keccak256( abi.encode(address(this), token, newAgent, sigExpire) ); bytes32 ethHash = messageHash.toEthSignedMessageHash(); require( ethHash.recover(tokenSig) == tokenSigners[token], "invalid token signature" ); require( ethHash.recover(bridgeSig) == bridgeSigner, "invalid bridge signature" ); } _pauseToken(token); // Transfer all the withhold balance of token to the new agent uint256 amount = IERC20(token).balanceOf(address(this)); if (amount > 0) { IERC20(token).safeTransfer(newAgent, amount); } emit Migrate(token, newAgent, amount); } /** * @dev Deposit a given amount to be claimed in another chain * * @param toChain chain ID in which the token amount will be claimed * @param token address of a registered token to be deposited * @param toWallet caller address that will claim the token from the {toChain} * @param amount wei amount of token to be deposited/claimed * @param bridgeSig signature issued by the Bridge Service * @param sigExpire nonce/expiration issued by the Bridge Service * * See chain-specific implementation for more documentation. */ function deposit( uint256 toChain, address token, address toWallet, uint256 amount, bytes memory bridgeSig, uint256 sigExpire ) external payable virtual; /** * @dev Transfers a given amount of token from agent to a user * * @param depositTx deposit transaction hash from another chain * @param token address of the local token to be claimed * @param amount wei amount of token to be claimed * @param tokenSig signature of the Token Owner (obtained via Bridge Service) * @param bridgeSig signature of the Bridge Service * * See chain-specific implementation for more documentation. */ function claim( bytes32 depositTx, address token, uint256 amount, bytes memory tokenSig, bytes memory bridgeSig ) external virtual; }
{ "evmVersion": "istanbul", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 1500 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_bridgeSigner","type":"address"},{"internalType":"address payable","name":"_treasurer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"depositTx","type":"bytes32"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"toWallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"toChain","type":"uint256"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"fromWallet","type":"address"},{"indexed":true,"internalType":"address","name":"toWallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"newAgent","type":"address"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"}],"name":"Migrate","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"baseToken","type":"address"},{"indexed":true,"internalType":"address","name":"signer","type":"address"}],"name":"Register","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousBridgeSigner","type":"address"},{"indexed":true,"internalType":"address","name":"newBridgeSigner","type":"address"}],"name":"SetBridgeSigner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address payable","name":"previousTreasurer","type":"address"},{"indexed":true,"internalType":"address payable","name":"newTreasurer","type":"address"}],"name":"SetTreasurer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"TokenPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"TokenUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"depositTx","type":"bytes32"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"tokenSig","type":"bytes"},{"internalType":"bytes","name":"bridgeSig","type":"bytes"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"toChain","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"toWallet","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"bridgeSig","type":"bytes"},{"internalType":"uint256","name":"sigExpire","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"newAgent","type":"address"},{"internalType":"bytes","name":"tokenSig","type":"bytes"},{"internalType":"bytes","name":"bridgeSig","type":"bytes"},{"internalType":"uint256","name":"sigExpire","type":"uint256"}],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"pauseToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"bridgeSig","type":"bytes"},{"internalType":"uint256","name":"sigExpire","type":"uint256"}],"name":"register","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newBrigdeSigner","type":"address"}],"name":"setBridgeSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"newTreasurer","type":"address"}],"name":"setTreasurer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenSigners","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasurer","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"unpauseToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162002a5538038062002a5583398101604081905262000034916200029a565b600080546001600160a01b03191633908117825560405184928492918291907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506000805460ff60a01b191690556200009182620000a6565b6200009c81620001a9565b50505050620002f1565b6000546001600160a01b03163314620000f55760405162461bcd60e51b8152602060048201819052602482015260008051602062002a3583398151915260448201526064015b60405180910390fd5b6001600160a01b0381166200014d5760405162461bcd60e51b815260206004820152601360248201527f656d70747920627269646765207369676e6572000000000000000000000000006044820152606401620000ec565b6001546040516001600160a01b038084169216907f149d692eda7ac02c9f4f8513da0e59ee3e9a72544738da92574d9f8bf579ff1e90600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314620001f45760405162461bcd60e51b8152602060048201819052602482015260008051602062002a358339815191526044820152606401620000ec565b6001600160a01b0381166200023e5760405162461bcd60e51b815260206004820152600f60248201526e32b6b83a3c903a3932b0b9bab932b960891b6044820152606401620000ec565b6002546040516001600160a01b038084169216907f1875a627112d4eedc536528e078f5f4c119d74f3c281d67bc096791825e4aabd90600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b60008060408385031215620002ad578182fd5b8251620002ba81620002d8565b6020840151909250620002cd81620002d8565b809150509250929050565b6001600160a01b0381168114620002ee57600080fd5b50565b61273480620003016000396000f3fe6080604052600436106101445760003560e01c8063671d6429116100c05780638da5cb5b11610074578063f2fde38b11610059578063f2fde38b1461035c578063fda49eb41461037c578063ffa1ad741461039c57600080fd5b80638da5cb5b1461031e578063e5fea93b1461033c57600080fd5b80637c41ad2c116100a55780637c41ad2c146102b95780638456cb59146102d95780638995881d146102ee57600080fd5b8063671d642914610284578063715018a6146102a457600080fd5b80634bfed4a1116101175780635c975abb116100fc5780635c975abb1461021957806363f901bb146102445780636542ab911461026457600080fd5b80634bfed4a1146101b3578063562aae68146101c657600080fd5b80630482a3381461014957806331938b781461015e5780633b3bff0f1461017e5780633f4ba83a1461019e575b600080fd5b61015c6101573660046125b1565b6103c3565b005b34801561016a57600080fd5b5061015c610179366004612512565b61076f565b34801561018a57600080fd5b5061015c6101993660046123df565b610bff565b3480156101aa57600080fd5b5061015c610c65565b61015c6101c13660046123fb565b610cc9565b3480156101d257600080fd5b506101fc6101e13660046123df565b6003602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561022557600080fd5b50600054600160a01b900460ff165b6040519015158152602001610210565b34801561025057600080fd5b506001546101fc906001600160a01b031681565b34801561027057600080fd5b5061015c61027f3660046123df565b6110cf565b34801561029057600080fd5b5061015c61029f3660046123df565b6111e8565b3480156102b057600080fd5b5061015c611301565b3480156102c557600080fd5b5061015c6102d43660046123df565b6113b2565b3480156102e557600080fd5b5061015c611415565b3480156102fa57600080fd5b506102346103093660046123df565b60046020526000908152604090205460ff1681565b34801561032a57600080fd5b506000546001600160a01b03166101fc565b34801561034857600080fd5b5061015c610357366004612476565b611477565b34801561036857600080fd5b5061015c6103773660046123df565b6119ad565b34801561038857600080fd5b506002546101fc906001600160a01b031681565b3480156103a857600080fd5b506103b1600181565b60405160ff9091168152602001610210565b8151602080840191909120600081815260059092526040909120548391839160ff161561042a5760405162461bcd60e51b815260206004820152601060248201526f726575736564207369676e617475726560801b60448201526064015b60405180910390fd5b6000818152600560205260409020805460ff19166001179055811561049757610455426103e861267c565b82116104975760405162461bcd60e51b815260206004820152601160248201527065787069726564207369676e617475726560781b6044820152606401610421565b600054600160a01b900460ff16156104e45760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610421565b6001600160a01b03881660009081526004602052604090205460ff161561053f5760405162461bcd60e51b815260206004820152600f60248201526e1d1bdad95b881a5cc81c185d5cd959608a1b6044820152606401610421565b6001600160a01b03888116600090815260036020526040902054166105a65760405162461bcd60e51b815260206004820152601460248201527f746f6b656e206e6f7420726567697374657265640000000000000000000000006044820152606401610421565b60408051306020808301919091528183018c90526001600160a01b038b811660608401528a16608083015260a082018990523460c083015260e080830188905283518084039091018152610100830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000061012084015261013c8084018290528451808503909101815261015c90930190935281519101206000906001549091506001600160a01b03166106618289611aeb565b6001600160a01b0316146106b75760405162461bcd60e51b815260206004820152601860248201527f696e76616c696420627269646765207369676e617475726500000000000000006044820152606401610421565b6106cc6001600160a01b038b1633308b611b66565b341561070d576002546040516001600160a01b03909116903480156108fc02916000818181858888f1935050505015801561070b573d6000803e3d6000fd5b505b604080518c8152602081018a905234918101919091526001600160a01b038a81169133918d16907ffbc8337b08322b8857dc82cc3ca875440af5059fc1e11b46ef736b1f571a47f4906060015b60405180910390a45050505050505050505050565b81516020808401919091206000818152600590925260408220548492919060ff16156107d05760405162461bcd60e51b815260206004820152601060248201526f726575736564207369676e617475726560801b6044820152606401610421565b6000818152600560205260409020805460ff19166001179055811561083d576107fb426103e861267c565b821161083d5760405162461bcd60e51b815260206004820152601160248201527065787069726564207369676e617475726560781b6044820152606401610421565b83516020808601919091206000818152600590925260408220548692919060ff161561089e5760405162461bcd60e51b815260206004820152601060248201526f726575736564207369676e617475726560801b6044820152606401610421565b6000818152600560205260409020805460ff19166001179055811561090b576108c9426103e861267c565b821161090b5760405162461bcd60e51b815260206004820152601160248201527065787069726564207369676e617475726560781b6044820152606401610421565b600054600160a01b900460ff16156109585760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610421565b6001600160a01b038a1660009081526004602052604090205460ff16156109b35760405162461bcd60e51b815260206004820152600f60248201526e1d1bdad95b881a5cc81c185d5cd959608a1b6044820152606401610421565b6001600160a01b038a811660009081526003602052604090205416610a1a5760405162461bcd60e51b815260206004820152601460248201527f746f6b656e206e6f7420726567697374657265640000000000000000000000006044820152606401610421565b60408051306020808301919091528183018e90526001600160a01b038d1660608301524660808301523360a083015260c08083018d90528351808403909101815260e0830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000061010084015261011c8084018290528451808503909101815261013c90930190935281519101206000906001600160a01b03808e1660009081526003602052604090205491925016610ada828c611aeb565b6001600160a01b031614610b305760405162461bcd60e51b815260206004820152601760248201527f696e76616c696420746f6b656e207369676e61747572650000000000000000006044820152606401610421565b6001546001600160a01b0316610b46828b611aeb565b6001600160a01b031614610b9c5760405162461bcd60e51b815260206004820152601860248201527f696e76616c696420627269646765207369676e617475726500000000000000006044820152606401610421565b5050610bb9610ba83390565b6001600160a01b038c16908b611c1d565b336001600160a01b03168a6001600160a01b03168c7fa45c018c08cffc1e5d85864e334de0f820678cb0f6278a9ee5ed170b2b3d94d78c60405161075a91815260200190565b6000546001600160a01b03163314610c595760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b610c6281611c6b565b50565b6000546001600160a01b03163314610cbf5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b610cc7611d1e565b565b8151602080840191909120600081815260059092526040909120548391839160ff1615610d2b5760405162461bcd60e51b815260206004820152601060248201526f726575736564207369676e617475726560801b6044820152606401610421565b6000818152600560205260409020805460ff191660011790558115610d9857610d56426103e861267c565b8211610d985760405162461bcd60e51b815260206004820152601160248201527065787069726564207369676e617475726560781b6044820152606401610421565b600054600160a01b900460ff1615610de55760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610421565b6001600160a01b038816610e3b5760405162461bcd60e51b815260206004820152600e60248201527f746f6b656e20697320656d7074790000000000000000000000000000000000006044820152606401610421565b6001600160a01b038716610e915760405162461bcd60e51b815260206004820152601260248201527f62617365546f6b656e20697320656d70747900000000000000000000000000006044820152606401610421565b6001600160a01b03881660009081526004602052604090205460ff1615610eec5760405162461bcd60e51b815260206004820152600f60248201526e1d1bdad95b881a5cc81c185d5cd959608a1b6044820152606401610421565b604080513060208083019190915233828401526001600160a01b038b811660608401528a81166080840152891660a08301523460c083015260e080830188905283518084039091018152610100830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000061012084015261013c8084018290528451808503909101815261015c90930190935281519101206000906001549091506001600160a01b0316610fa78289611aeb565b6001600160a01b031614610ffd5760405162461bcd60e51b815260206004820152601860248201527f696e76616c696420627269646765207369676e617475726500000000000000006044820152606401610421565b50506001600160a01b038881166000908152600360205260409020805473ffffffffffffffffffffffffffffffffffffffff1916918816919091179055341561107b576002546040516001600160a01b03909116903480156108fc02916000818181858888f19350505050158015611079573d6000803e3d6000fd5b505b856001600160a01b0316876001600160a01b0316896001600160a01b03167f2a01ad7aa2d2f1a30ca9240162484085719a1dc4706f26467cb3c097dce6ca1b60405160405180910390a45050505050505050565b6000546001600160a01b031633146111295760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b6001600160a01b03811661117f5760405162461bcd60e51b815260206004820152601360248201527f656d70747920627269646765207369676e6572000000000000000000000000006044820152606401610421565b6001546040516001600160a01b038084169216907f149d692eda7ac02c9f4f8513da0e59ee3e9a72544738da92574d9f8bf579ff1e90600090a36001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000546001600160a01b031633146112425760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b6001600160a01b0381166112985760405162461bcd60e51b815260206004820152600f60248201527f656d7074792074726561737572657200000000000000000000000000000000006044820152606401610421565b6002546040516001600160a01b038084169216907f1875a627112d4eedc536528e078f5f4c119d74f3c281d67bc096791825e4aabd90600090a36002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461135b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b6000546001600160a01b0316331461140c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b610c6281611ddf565b6000546001600160a01b0316331461146f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b610cc7611e96565b8251602080850191909120600081815260059092526040909120548491839160ff16156114d95760405162461bcd60e51b815260206004820152601060248201526f726575736564207369676e617475726560801b6044820152606401610421565b6000818152600560205260409020805460ff19166001179055811561154657611504426103e861267c565b82116115465760405162461bcd60e51b815260206004820152601160248201527065787069726564207369676e617475726560781b6044820152606401610421565b8451602080870191909120600081815260059092526040909120548691869160ff16156115a85760405162461bcd60e51b815260206004820152601060248201526f726575736564207369676e617475726560801b6044820152606401610421565b6000818152600560205260409020805460ff191660011790558115611615576115d3426103e861267c565b82116116155760405162461bcd60e51b815260206004820152601160248201527065787069726564207369676e617475726560781b6044820152606401610421565b600054600160a01b900460ff16156116625760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610421565b6001600160a01b038b1660009081526004602052604090205460ff16156116bd5760405162461bcd60e51b815260206004820152600f60248201526e1d1bdad95b881a5cc81c185d5cd959608a1b6044820152606401610421565b6001600160a01b038b8116600090815260036020526040902054166117245760405162461bcd60e51b815260206004820152601460248201527f746f6b656e206e6f7420726567697374657265640000000000000000000000006044820152606401610421565b60408051306020808301919091526001600160a01b038e8116838501528d16606083015260808083018b90528351808403909101815260a0830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000060c084015260dc8084018290528451808503909101815260fc90930190935281519101206000906001600160a01b03808f16600090815260036020526040902054919250166117d6828d611aeb565b6001600160a01b03161461182c5760405162461bcd60e51b815260206004820152601760248201527f696e76616c696420746f6b656e207369676e61747572650000000000000000006044820152606401610421565b6001546001600160a01b0316611842828c611aeb565b6001600160a01b0316146118985760405162461bcd60e51b815260206004820152601860248201527f696e76616c696420627269646765207369676e617475726500000000000000006044820152606401610421565b50506118a38b611ddf565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038d16906370a082319060240160206040518083038186803b1580156118fe57600080fd5b505afa158015611912573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119369190612599565b90508015611952576119526001600160a01b038d168c83611c1d565b8a6001600160a01b03168c6001600160a01b03167f18df02dcc52b9c494f391df09661519c0069bd8540141946280399408205ca1a8360405161199791815260200190565b60405180910390a3505050505050505050505050565b6000546001600160a01b03163314611a075760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b6001600160a01b038116611a835760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610421565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60008151604114611b3e5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610421565b60208201516040830151606084015160001a611b5c86828585611f39565b9695505050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611c179085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526120e2565b50505050565b6040516001600160a01b038316602482015260448101829052611c669084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611bb3565b505050565b6001600160a01b03811660009081526004602052604090205460ff16611cd35760405162461bcd60e51b815260206004820152601360248201527f746f6b656e206973206e6f7420706175736564000000000000000000000000006044820152606401610421565b6001600160a01b038116600081815260046020526040808220805460ff19169055513392917fa5bb93d2ab7320f11fa3d7af4ef8d6d3be3845fb3cbc5e0e177fb7c36a22591d91a350565b600054600160a01b900460ff16611d775760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610421565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b03811660009081526004602052604090205460ff1615611e485760405162461bcd60e51b815260206004820152601760248201527f746f6b656e20697320616c7265616479207061757365640000000000000000006044820152606401610421565b6001600160a01b038116600081815260046020526040808220805460ff19166001179055513392917f3049c79d2929992d0f7fdd893166d6b11cc50f9c20d83ba5ea22091b7f1276d591a350565b600054600160a01b900460ff1615611ee35760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610421565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611dc23390565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611fb65760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610421565b8360ff16601b1480611fcb57508360ff16601c145b6120225760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610421565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015612076573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166120d95760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610421565b95945050505050565b6000612137826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166121c79092919063ffffffff16565b805190915015611c66578080602001905181019061215591906124f2565b611c665760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610421565b60606121d684846000856121e0565b90505b9392505050565b6060824710156122585760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610421565b843b6122a65760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610421565b600080866001600160a01b031685876040516122c2919061262d565b60006040518083038185875af1925050503d80600081146122ff576040519150601f19603f3d011682016040523d82523d6000602084013e612304565b606091505b509150915061231482828661231f565b979650505050505050565b6060831561232e5750816121d9565b82511561233e5782518084602001fd5b8160405162461bcd60e51b81526004016104219190612649565b600082601f830112612368578081fd5b813567ffffffffffffffff80821115612383576123836126d3565b604051601f8301601f19908116603f011681019082821181831017156123ab576123ab6126d3565b816040528381528660208588010111156123c3578485fd5b8360208701602083013792830160200193909352509392505050565b6000602082840312156123f0578081fd5b81356121d9816126e9565b600080600080600060a08688031215612412578081fd5b853561241d816126e9565b9450602086013561242d816126e9565b9350604086013561243d816126e9565b9250606086013567ffffffffffffffff811115612458578182fd5b61246488828901612358565b95989497509295608001359392505050565b600080600080600060a0868803121561248d578081fd5b8535612498816126e9565b945060208601356124a8816126e9565b9350604086013567ffffffffffffffff808211156124c4578283fd5b6124d089838a01612358565b945060608801359150808211156124e5578283fd5b5061246488828901612358565b600060208284031215612503578081fd5b815180151581146121d9578182fd5b600080600080600060a08688031215612529578081fd5b85359450602086013561253b816126e9565b935060408601359250606086013567ffffffffffffffff8082111561255e578283fd5b61256a89838a01612358565b9350608088013591508082111561257f578283fd5b5061258c88828901612358565b9150509295509295909350565b6000602082840312156125aa578081fd5b5051919050565b60008060008060008060c087890312156125c9578081fd5b8635955060208701356125db816126e9565b945060408701356125eb816126e9565b935060608701359250608087013567ffffffffffffffff81111561260d578182fd5b61261989828a01612358565b92505060a087013590509295509295509295565b6000825161263f8184602087016126a7565b9190910192915050565b60208152600082518060208401526126688160408501602087016126a7565b601f01601f19169190910160400192915050565b60008160001904831182151516156126a257634e487b7160e01b81526011600452602481fd5b500290565b60005b838110156126c25781810151838201526020016126aa565b83811115611c175750506000910152565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610c6257600080fdfea2646970667358221220d76edd234ce48a8912abe2a9a24afbd6de6cecf6c1b64e25648889dc48a0145764736f6c634300080400334f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657200000000000000000000000072c509b36f734567b86e6b624ba4d53ea5043718000000000000000000000000d020f2160cef2e4d70431c2f3bba506ea6a618d4
Deployed Bytecode
0x6080604052600436106101445760003560e01c8063671d6429116100c05780638da5cb5b11610074578063f2fde38b11610059578063f2fde38b1461035c578063fda49eb41461037c578063ffa1ad741461039c57600080fd5b80638da5cb5b1461031e578063e5fea93b1461033c57600080fd5b80637c41ad2c116100a55780637c41ad2c146102b95780638456cb59146102d95780638995881d146102ee57600080fd5b8063671d642914610284578063715018a6146102a457600080fd5b80634bfed4a1116101175780635c975abb116100fc5780635c975abb1461021957806363f901bb146102445780636542ab911461026457600080fd5b80634bfed4a1146101b3578063562aae68146101c657600080fd5b80630482a3381461014957806331938b781461015e5780633b3bff0f1461017e5780633f4ba83a1461019e575b600080fd5b61015c6101573660046125b1565b6103c3565b005b34801561016a57600080fd5b5061015c610179366004612512565b61076f565b34801561018a57600080fd5b5061015c6101993660046123df565b610bff565b3480156101aa57600080fd5b5061015c610c65565b61015c6101c13660046123fb565b610cc9565b3480156101d257600080fd5b506101fc6101e13660046123df565b6003602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561022557600080fd5b50600054600160a01b900460ff165b6040519015158152602001610210565b34801561025057600080fd5b506001546101fc906001600160a01b031681565b34801561027057600080fd5b5061015c61027f3660046123df565b6110cf565b34801561029057600080fd5b5061015c61029f3660046123df565b6111e8565b3480156102b057600080fd5b5061015c611301565b3480156102c557600080fd5b5061015c6102d43660046123df565b6113b2565b3480156102e557600080fd5b5061015c611415565b3480156102fa57600080fd5b506102346103093660046123df565b60046020526000908152604090205460ff1681565b34801561032a57600080fd5b506000546001600160a01b03166101fc565b34801561034857600080fd5b5061015c610357366004612476565b611477565b34801561036857600080fd5b5061015c6103773660046123df565b6119ad565b34801561038857600080fd5b506002546101fc906001600160a01b031681565b3480156103a857600080fd5b506103b1600181565b60405160ff9091168152602001610210565b8151602080840191909120600081815260059092526040909120548391839160ff161561042a5760405162461bcd60e51b815260206004820152601060248201526f726575736564207369676e617475726560801b60448201526064015b60405180910390fd5b6000818152600560205260409020805460ff19166001179055811561049757610455426103e861267c565b82116104975760405162461bcd60e51b815260206004820152601160248201527065787069726564207369676e617475726560781b6044820152606401610421565b600054600160a01b900460ff16156104e45760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610421565b6001600160a01b03881660009081526004602052604090205460ff161561053f5760405162461bcd60e51b815260206004820152600f60248201526e1d1bdad95b881a5cc81c185d5cd959608a1b6044820152606401610421565b6001600160a01b03888116600090815260036020526040902054166105a65760405162461bcd60e51b815260206004820152601460248201527f746f6b656e206e6f7420726567697374657265640000000000000000000000006044820152606401610421565b60408051306020808301919091528183018c90526001600160a01b038b811660608401528a16608083015260a082018990523460c083015260e080830188905283518084039091018152610100830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000061012084015261013c8084018290528451808503909101815261015c90930190935281519101206000906001549091506001600160a01b03166106618289611aeb565b6001600160a01b0316146106b75760405162461bcd60e51b815260206004820152601860248201527f696e76616c696420627269646765207369676e617475726500000000000000006044820152606401610421565b6106cc6001600160a01b038b1633308b611b66565b341561070d576002546040516001600160a01b03909116903480156108fc02916000818181858888f1935050505015801561070b573d6000803e3d6000fd5b505b604080518c8152602081018a905234918101919091526001600160a01b038a81169133918d16907ffbc8337b08322b8857dc82cc3ca875440af5059fc1e11b46ef736b1f571a47f4906060015b60405180910390a45050505050505050505050565b81516020808401919091206000818152600590925260408220548492919060ff16156107d05760405162461bcd60e51b815260206004820152601060248201526f726575736564207369676e617475726560801b6044820152606401610421565b6000818152600560205260409020805460ff19166001179055811561083d576107fb426103e861267c565b821161083d5760405162461bcd60e51b815260206004820152601160248201527065787069726564207369676e617475726560781b6044820152606401610421565b83516020808601919091206000818152600590925260408220548692919060ff161561089e5760405162461bcd60e51b815260206004820152601060248201526f726575736564207369676e617475726560801b6044820152606401610421565b6000818152600560205260409020805460ff19166001179055811561090b576108c9426103e861267c565b821161090b5760405162461bcd60e51b815260206004820152601160248201527065787069726564207369676e617475726560781b6044820152606401610421565b600054600160a01b900460ff16156109585760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610421565b6001600160a01b038a1660009081526004602052604090205460ff16156109b35760405162461bcd60e51b815260206004820152600f60248201526e1d1bdad95b881a5cc81c185d5cd959608a1b6044820152606401610421565b6001600160a01b038a811660009081526003602052604090205416610a1a5760405162461bcd60e51b815260206004820152601460248201527f746f6b656e206e6f7420726567697374657265640000000000000000000000006044820152606401610421565b60408051306020808301919091528183018e90526001600160a01b038d1660608301524660808301523360a083015260c08083018d90528351808403909101815260e0830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000061010084015261011c8084018290528451808503909101815261013c90930190935281519101206000906001600160a01b03808e1660009081526003602052604090205491925016610ada828c611aeb565b6001600160a01b031614610b305760405162461bcd60e51b815260206004820152601760248201527f696e76616c696420746f6b656e207369676e61747572650000000000000000006044820152606401610421565b6001546001600160a01b0316610b46828b611aeb565b6001600160a01b031614610b9c5760405162461bcd60e51b815260206004820152601860248201527f696e76616c696420627269646765207369676e617475726500000000000000006044820152606401610421565b5050610bb9610ba83390565b6001600160a01b038c16908b611c1d565b336001600160a01b03168a6001600160a01b03168c7fa45c018c08cffc1e5d85864e334de0f820678cb0f6278a9ee5ed170b2b3d94d78c60405161075a91815260200190565b6000546001600160a01b03163314610c595760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b610c6281611c6b565b50565b6000546001600160a01b03163314610cbf5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b610cc7611d1e565b565b8151602080840191909120600081815260059092526040909120548391839160ff1615610d2b5760405162461bcd60e51b815260206004820152601060248201526f726575736564207369676e617475726560801b6044820152606401610421565b6000818152600560205260409020805460ff191660011790558115610d9857610d56426103e861267c565b8211610d985760405162461bcd60e51b815260206004820152601160248201527065787069726564207369676e617475726560781b6044820152606401610421565b600054600160a01b900460ff1615610de55760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610421565b6001600160a01b038816610e3b5760405162461bcd60e51b815260206004820152600e60248201527f746f6b656e20697320656d7074790000000000000000000000000000000000006044820152606401610421565b6001600160a01b038716610e915760405162461bcd60e51b815260206004820152601260248201527f62617365546f6b656e20697320656d70747900000000000000000000000000006044820152606401610421565b6001600160a01b03881660009081526004602052604090205460ff1615610eec5760405162461bcd60e51b815260206004820152600f60248201526e1d1bdad95b881a5cc81c185d5cd959608a1b6044820152606401610421565b604080513060208083019190915233828401526001600160a01b038b811660608401528a81166080840152891660a08301523460c083015260e080830188905283518084039091018152610100830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000061012084015261013c8084018290528451808503909101815261015c90930190935281519101206000906001549091506001600160a01b0316610fa78289611aeb565b6001600160a01b031614610ffd5760405162461bcd60e51b815260206004820152601860248201527f696e76616c696420627269646765207369676e617475726500000000000000006044820152606401610421565b50506001600160a01b038881166000908152600360205260409020805473ffffffffffffffffffffffffffffffffffffffff1916918816919091179055341561107b576002546040516001600160a01b03909116903480156108fc02916000818181858888f19350505050158015611079573d6000803e3d6000fd5b505b856001600160a01b0316876001600160a01b0316896001600160a01b03167f2a01ad7aa2d2f1a30ca9240162484085719a1dc4706f26467cb3c097dce6ca1b60405160405180910390a45050505050505050565b6000546001600160a01b031633146111295760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b6001600160a01b03811661117f5760405162461bcd60e51b815260206004820152601360248201527f656d70747920627269646765207369676e6572000000000000000000000000006044820152606401610421565b6001546040516001600160a01b038084169216907f149d692eda7ac02c9f4f8513da0e59ee3e9a72544738da92574d9f8bf579ff1e90600090a36001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000546001600160a01b031633146112425760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b6001600160a01b0381166112985760405162461bcd60e51b815260206004820152600f60248201527f656d7074792074726561737572657200000000000000000000000000000000006044820152606401610421565b6002546040516001600160a01b038084169216907f1875a627112d4eedc536528e078f5f4c119d74f3c281d67bc096791825e4aabd90600090a36002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461135b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b6000546001600160a01b0316331461140c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b610c6281611ddf565b6000546001600160a01b0316331461146f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b610cc7611e96565b8251602080850191909120600081815260059092526040909120548491839160ff16156114d95760405162461bcd60e51b815260206004820152601060248201526f726575736564207369676e617475726560801b6044820152606401610421565b6000818152600560205260409020805460ff19166001179055811561154657611504426103e861267c565b82116115465760405162461bcd60e51b815260206004820152601160248201527065787069726564207369676e617475726560781b6044820152606401610421565b8451602080870191909120600081815260059092526040909120548691869160ff16156115a85760405162461bcd60e51b815260206004820152601060248201526f726575736564207369676e617475726560801b6044820152606401610421565b6000818152600560205260409020805460ff191660011790558115611615576115d3426103e861267c565b82116116155760405162461bcd60e51b815260206004820152601160248201527065787069726564207369676e617475726560781b6044820152606401610421565b600054600160a01b900460ff16156116625760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610421565b6001600160a01b038b1660009081526004602052604090205460ff16156116bd5760405162461bcd60e51b815260206004820152600f60248201526e1d1bdad95b881a5cc81c185d5cd959608a1b6044820152606401610421565b6001600160a01b038b8116600090815260036020526040902054166117245760405162461bcd60e51b815260206004820152601460248201527f746f6b656e206e6f7420726567697374657265640000000000000000000000006044820152606401610421565b60408051306020808301919091526001600160a01b038e8116838501528d16606083015260808083018b90528351808403909101815260a0830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000060c084015260dc8084018290528451808503909101815260fc90930190935281519101206000906001600160a01b03808f16600090815260036020526040902054919250166117d6828d611aeb565b6001600160a01b03161461182c5760405162461bcd60e51b815260206004820152601760248201527f696e76616c696420746f6b656e207369676e61747572650000000000000000006044820152606401610421565b6001546001600160a01b0316611842828c611aeb565b6001600160a01b0316146118985760405162461bcd60e51b815260206004820152601860248201527f696e76616c696420627269646765207369676e617475726500000000000000006044820152606401610421565b50506118a38b611ddf565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038d16906370a082319060240160206040518083038186803b1580156118fe57600080fd5b505afa158015611912573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119369190612599565b90508015611952576119526001600160a01b038d168c83611c1d565b8a6001600160a01b03168c6001600160a01b03167f18df02dcc52b9c494f391df09661519c0069bd8540141946280399408205ca1a8360405161199791815260200190565b60405180910390a3505050505050505050505050565b6000546001600160a01b03163314611a075760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610421565b6001600160a01b038116611a835760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610421565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60008151604114611b3e5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610421565b60208201516040830151606084015160001a611b5c86828585611f39565b9695505050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611c179085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526120e2565b50505050565b6040516001600160a01b038316602482015260448101829052611c669084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611bb3565b505050565b6001600160a01b03811660009081526004602052604090205460ff16611cd35760405162461bcd60e51b815260206004820152601360248201527f746f6b656e206973206e6f7420706175736564000000000000000000000000006044820152606401610421565b6001600160a01b038116600081815260046020526040808220805460ff19169055513392917fa5bb93d2ab7320f11fa3d7af4ef8d6d3be3845fb3cbc5e0e177fb7c36a22591d91a350565b600054600160a01b900460ff16611d775760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610421565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b03811660009081526004602052604090205460ff1615611e485760405162461bcd60e51b815260206004820152601760248201527f746f6b656e20697320616c7265616479207061757365640000000000000000006044820152606401610421565b6001600160a01b038116600081815260046020526040808220805460ff19166001179055513392917f3049c79d2929992d0f7fdd893166d6b11cc50f9c20d83ba5ea22091b7f1276d591a350565b600054600160a01b900460ff1615611ee35760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610421565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611dc23390565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611fb65760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610421565b8360ff16601b1480611fcb57508360ff16601c145b6120225760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610421565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015612076573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166120d95760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610421565b95945050505050565b6000612137826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166121c79092919063ffffffff16565b805190915015611c66578080602001905181019061215591906124f2565b611c665760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610421565b60606121d684846000856121e0565b90505b9392505050565b6060824710156122585760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610421565b843b6122a65760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610421565b600080866001600160a01b031685876040516122c2919061262d565b60006040518083038185875af1925050503d80600081146122ff576040519150601f19603f3d011682016040523d82523d6000602084013e612304565b606091505b509150915061231482828661231f565b979650505050505050565b6060831561232e5750816121d9565b82511561233e5782518084602001fd5b8160405162461bcd60e51b81526004016104219190612649565b600082601f830112612368578081fd5b813567ffffffffffffffff80821115612383576123836126d3565b604051601f8301601f19908116603f011681019082821181831017156123ab576123ab6126d3565b816040528381528660208588010111156123c3578485fd5b8360208701602083013792830160200193909352509392505050565b6000602082840312156123f0578081fd5b81356121d9816126e9565b600080600080600060a08688031215612412578081fd5b853561241d816126e9565b9450602086013561242d816126e9565b9350604086013561243d816126e9565b9250606086013567ffffffffffffffff811115612458578182fd5b61246488828901612358565b95989497509295608001359392505050565b600080600080600060a0868803121561248d578081fd5b8535612498816126e9565b945060208601356124a8816126e9565b9350604086013567ffffffffffffffff808211156124c4578283fd5b6124d089838a01612358565b945060608801359150808211156124e5578283fd5b5061246488828901612358565b600060208284031215612503578081fd5b815180151581146121d9578182fd5b600080600080600060a08688031215612529578081fd5b85359450602086013561253b816126e9565b935060408601359250606086013567ffffffffffffffff8082111561255e578283fd5b61256a89838a01612358565b9350608088013591508082111561257f578283fd5b5061258c88828901612358565b9150509295509295909350565b6000602082840312156125aa578081fd5b5051919050565b60008060008060008060c087890312156125c9578081fd5b8635955060208701356125db816126e9565b945060408701356125eb816126e9565b935060608701359250608087013567ffffffffffffffff81111561260d578182fd5b61261989828a01612358565b92505060a087013590509295509295509295565b6000825161263f8184602087016126a7565b9190910192915050565b60208152600082518060208401526126688160408501602087016126a7565b601f01601f19169190910160400192915050565b60008160001904831182151516156126a257634e487b7160e01b81526011600452602481fd5b500290565b60005b838110156126c25781810151838201526020016126aa565b83811115611c175750506000910152565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610c6257600080fdfea2646970667358221220d76edd234ce48a8912abe2a9a24afbd6de6cecf6c1b64e25648889dc48a0145764736f6c63430008040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000072c509b36f734567b86e6b624ba4d53ea5043718000000000000000000000000d020f2160cef2e4d70431c2f3bba506ea6a618d4
-----Decoded View---------------
Arg [0] : _bridgeSigner (address): 0x72c509b36f734567b86E6B624ba4d53eA5043718
Arg [1] : _treasurer (address): 0xD020f2160cef2e4d70431c2f3BBA506eA6a618D4
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000072c509b36f734567b86e6b624ba4d53ea5043718
Arg [1] : 000000000000000000000000d020f2160cef2e4d70431c2f3bba506ea6a618d4
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.048268 | 11,739,158.61 | $566,620.66 |
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.