My Name Tag:
Not Available, login to update
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Source Code Verified (Exact Match)
Contract Name:
Vault
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) 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() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { 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 { _transferOwnership(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"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) 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) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @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 { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. 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. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @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) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // 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 (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): 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. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @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) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @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 Message, created from `s`. 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(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @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 // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.0; import "./ECDSA.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ */ abstract contract EIP712 { /* solhint-disable var-name-mixedcase */ // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID; address private immutable _CACHED_THIS; bytes32 private immutable _HASHED_NAME; bytes32 private immutable _HASHED_VERSION; bytes32 private immutable _TYPE_HASH; /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); bytes32 typeHash = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; _CACHED_CHAIN_ID = block.chainid; _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); _CACHED_THIS = address(this); _TYPE_HASH = typeHash; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) { return _CACHED_DOMAIN_SEPARATOR; } else { return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); } } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
pragma solidity 0.8.17; interface IBridge { // CBridge function send( address _receiver, address _token, uint256 _amount, uint64 _dstChainId, uint64 _nonce, uint32 _maxSilippage ) external; function sendNative( address _receiver, uint256 _amount, uint64 _dstChainId, uint64 _nonce, uint32 _maxSlippage ) external payable; function withdraw( bytes calldata _wdmsg, bytes[] memory _sigs, address[] memory _signers, uint256[] memory _powers ) external; //polyBridge function lock( address fromAsset, uint64 toChainId, bytes memory toAddress, uint256 amount, uint256 fee, uint256 id ) external payable; //PortalBridge function transferTokensWithPayload( address token, uint256 amount, uint16 recipientChain, bytes32 recipient, uint32 nonce, bytes memory payload ) external payable; function wrapAndTransferETHWithPayload( uint16 recipientChain, bytes32 recipient, uint32 nonce, bytes memory payload ) external payable; function transferTokens( address token, uint256 amount, uint16 recipientChain, bytes32 recipient, uint256 arbiterFee, uint32 nonce ) external payable returns (uint64 sequence); function wrapAndTransferETH( uint16 recipientChain, bytes32 recipient, uint256 arbiterFee, uint32 nonce ) external payable returns (uint64 sequence); function completeTransferWithPayload(bytes memory encodeVm) external returns (bytes memory); function completeTransferAndUnwrapETHWithPayload(bytes memory encodeVm) external returns (bytes memory); //MultichainBridge function anySwapOutUnderlying( address token, address to, uint256 amount, uint256 toChainID ) external; function anySwapOut( address token, address to, uint256 amount, uint256 toChainID ) external; function anySwapOutNative( address token, address to, uint256 toChainID ) external payable; function wNATIVE() external returns (address); function transfers(bytes32 transferId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.17; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.17; interface ISigsVerifier { /** * @notice Verifies that a message is signed by a quorum among the signers. * @param _msg signed message * @param _sigs list of signatures sorted by signer addresses * @param _signers sorted list of current signers * @param _powers powers of current signers */ function verifySigs( bytes memory _msg, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external view; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import "../libraries/SafeERC20.sol"; using SafeERC20 for IERC20; struct BridgeInfo { string bridge; address dstToken; uint64 chainId; uint256 amount; address user; uint64 nonce; } struct CBridgeDescription { address srcToken; uint256 amount; address receiver; uint64 dstChainId; uint64 nonce; uint32 maxSlippage; } struct SwapData { address user; address srcToken; address dstToken; uint256 amount; bytes callData; } struct MultiChainDescription { address srcToken; uint256 amount; address receiver; uint64 dstChainId; uint64 nonce; address router; } struct PolyBridgeDescription { address fromAsset; uint64 toChainId; bytes toAddress; uint256 amount; uint256 fee; uint256 id; uint64 nonce; } struct PortalBridgeDescription { address token; uint256 amount; uint16 recipientChain; address recipient; uint32 nonce; uint256 arbiterFee; bytes payload; } struct AnyMapping { address tokenAddress; address anyTokenAddress; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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"); (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"); (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"); (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"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
pragma solidity 0.8.17; import "./SafeERC20.sol"; library AssetLib { using SafeERC20 for IERC20; uint256 private constant MAX_UINT = type(uint256).max; address internal constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; function getBalance(address token) internal view returns (uint256) { return token == NATIVE_ADDRESS ? address(this).balance : IERC20(token).balanceOf(address(this)); } function userBalance(address user, address token) internal view returns (uint256) { return token == NATIVE_ADDRESS ? user.balance : IERC20(token).balanceOf(user); } }
pragma solidity 0.8.17; library OrderLib { struct Order { uint256 salt; address makerAsset; address takerAsset; address maker; address receiver; address allowedSender; // equals to Zero address on public orders uint256 makingAmount; uint256 takingAmount; uint256 offsets; // bytes makerAssetData; // bytes takerAssetData; // bytes getMakingAmount; // this.staticcall(abi.encodePacked(bytes, swapTakerAmount)) => (swapMakerAmount) // bytes getTakingAmount; // this.staticcall(abi.encodePacked(bytes, swapMakerAmount)) => (swapTakerAmount) // bytes predicate; // this.staticcall(bytes) => (bool) // bytes permit; // On first fill: permit.1.call(abi.encodePacked(permit.selector, permit.2)) // bytes preInteraction; // bytes postInteraction; bytes interactions; // concat(makerAssetData, takerAssetData, getMakingAmount, getTakingAmount, predicate, permit, preIntercation, postInteraction) } struct OrderRFQ { uint256 info; // lowest 64 bits is the order id, next 64 bits is the expiration timestamp address makerAsset; address takerAsset; address maker; address allowedSender; // equals to Zero address on public orders uint256 makingAmount; uint256 takingAmount; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.17; // runtime proto sol library library Pb { enum WireType { Varint, Fixed64, LengthDelim, StartGroup, EndGroup, Fixed32 } struct Buffer { uint256 idx; // the start index of next read. when idx=b.length, we're done bytes b; // hold serialized proto msg, readonly } // create a new in-memory Buffer object from raw msg bytes function fromBytes(bytes memory raw) internal pure returns (Buffer memory buf) { buf.b = raw; buf.idx = 0; } // whether there are unread bytes function hasMore(Buffer memory buf) internal pure returns (bool) { return buf.idx < buf.b.length; } // decode current field number and wiretype function decKey(Buffer memory buf) internal pure returns (uint256 tag, WireType wiretype) { uint256 v = decVarint(buf); tag = v / 8; wiretype = WireType(v & 7); } // count tag occurrences, return an array due to no memory map support // have to create array for (maxtag+1) size. cnts[tag] = occurrences // should keep buf.idx unchanged because this is only a count function function cntTags(Buffer memory buf, uint256 maxtag) internal pure returns (uint256[] memory cnts) { uint256 originalIdx = buf.idx; cnts = new uint256[](maxtag + 1); // protobuf's tags are from 1 rather than 0 uint256 tag; WireType wire; while (hasMore(buf)) { (tag, wire) = decKey(buf); cnts[tag] += 1; skipValue(buf, wire); } buf.idx = originalIdx; } // read varint from current buf idx, move buf.idx to next read, return the int value function decVarint(Buffer memory buf) internal pure returns (uint256 v) { bytes10 tmp; // proto int is at most 10 bytes (7 bits can be used per byte) bytes memory bb = buf.b; // get buf.b mem addr to use in assembly v = buf.idx; // use v to save one additional uint variable assembly { tmp := mload(add(add(bb, 32), v)) // load 10 bytes from buf.b[buf.idx] to tmp } uint256 b; // store current byte content v = 0; // reset to 0 for return value for (uint256 i = 0; i < 10; i++) { assembly { b := byte(i, tmp) // don't use tmp[i] because it does bound check and costs extra } v |= (b & 0x7F) << (i * 7); if (b & 0x80 == 0) { buf.idx += i + 1; return v; } } revert(); // i=10, invalid varint stream } // read length delimited field and return bytes function decBytes(Buffer memory buf) internal pure returns (bytes memory b) { uint256 len = decVarint(buf); uint256 end = buf.idx + len; require(end <= buf.b.length); // avoid overflow b = new bytes(len); bytes memory bufB = buf.b; // get buf.b mem addr to use in assembly uint256 bStart; uint256 bufBStart = buf.idx; assembly { bStart := add(b, 32) bufBStart := add(add(bufB, 32), bufBStart) } for (uint256 i = 0; i < len; i += 32) { assembly { mstore(add(bStart, i), mload(add(bufBStart, i))) } } buf.idx = end; } // return packed ints function decPacked(Buffer memory buf) internal pure returns (uint256[] memory t) { uint256 len = decVarint(buf); uint256 end = buf.idx + len; require(end <= buf.b.length); // avoid overflow // array in memory must be init w/ known length // so we have to create a tmp array w/ max possible len first uint256[] memory tmp = new uint256[](len); uint256 i = 0; // count how many ints are there while (buf.idx < end) { tmp[i] = decVarint(buf); i++; } t = new uint256[](i); // init t with correct length for (uint256 j = 0; j < i; j++) { t[j] = tmp[j]; } return t; } // move idx pass current value field, to beginning of next tag or msg end function skipValue(Buffer memory buf, WireType wire) internal pure { if (wire == WireType.Varint) { decVarint(buf); } else if (wire == WireType.LengthDelim) { uint256 len = decVarint(buf); buf.idx += len; // skip len bytes value data require(buf.idx <= buf.b.length); // avoid overflow } else { revert(); } // unsupported wiretype } // type conversion help utils function _bool(uint256 x) internal pure returns (bool v) { return x != 0; } function _uint256(bytes memory b) internal pure returns (uint256 v) { require(b.length <= 32); // b's length must be smaller than or equal to 32 assembly { v := mload(add(b, 32)) } // load all 32bytes to v v = v >> (8 * (32 - b.length)); // only first b.length is valid } function _address(bytes memory b) internal pure returns (address v) { v = _addressPayable(b); } function _addressPayable(bytes memory b) internal pure returns (address payable v) { require(b.length == 20); //load 32bytes then shift right 12 bytes assembly { v := div(mload(add(b, 32)), 0x1000000000000000000000000) } } function _bytes32(bytes memory b) internal pure returns (bytes32 v) { require(b.length == 32); assembly { v := mload(add(b, 32)) } } // uint[] to uint8[] function uint8s(uint256[] memory arr) internal pure returns (uint8[] memory t) { t = new uint8[](arr.length); for (uint256 i = 0; i < t.length; i++) { t[i] = uint8(arr[i]); } } function uint32s(uint256[] memory arr) internal pure returns (uint32[] memory t) { t = new uint32[](arr.length); for (uint256 i = 0; i < t.length; i++) { t[i] = uint32(arr[i]); } } function uint64s(uint256[] memory arr) internal pure returns (uint64[] memory t) { t = new uint64[](arr.length); for (uint256 i = 0; i < t.length; i++) { t[i] = uint64(arr[i]); } } function bools(uint256[] memory arr) internal pure returns (bool[] memory t) { t = new bool[](arr.length); for (uint256 i = 0; i < t.length; i++) { t[i] = arr[i] != 0; } } }
// SPDX-License-Identifier: GPL-3.0-only // Code generated by protoc-gen-sol. DO NOT EDIT. // source: contracts/libraries/proto/pool.proto pragma solidity 0.8.17; import "./Pb.sol"; library PbPool { using Pb for Pb.Buffer; // so we can call Pb funcs on Buffer obj struct WithdrawMsg { uint64 chainid; // tag: 1 uint64 seqnum; // tag: 2 address receiver; // tag: 3 address token; // tag: 4 uint256 amount; // tag: 5 bytes32 refid; // tag: 6 } // end struct WithdrawMsg function decWithdrawMsg(bytes memory raw) internal pure returns (WithdrawMsg memory m) { Pb.Buffer memory buf = Pb.fromBytes(raw); uint256 tag; Pb.WireType wire; while (buf.hasMore()) { (tag, wire) = buf.decKey(); if (false) {} // solidity has no switch/case else if (tag == 1) { m.chainid = uint64(buf.decVarint()); } else if (tag == 2) { m.seqnum = uint64(buf.decVarint()); } else if (tag == 3) { m.receiver = Pb._address(buf.decBytes()); } else if (tag == 4) { m.token = Pb._address(buf.decBytes()); } else if (tag == 5) { m.amount = Pb._uint256(buf.decBytes()); } else if (tag == 6) { m.refid = Pb._bytes32(buf.decBytes()); } else { buf.skipValue(wire); } // skip value of unknown tag } } // end decoder WithdrawMsg }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../interfaces/IERC20.sol"; import "./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' 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 require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.17; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "../interfaces/ISigsVerifier.sol"; contract Signers is Ownable, ISigsVerifier { using ECDSA for bytes32; bytes32 public ssHash; uint256 public triggerTime; // timestamp when last update was triggered // reset can be called by the owner address for emergency recovery uint256 public resetTime; uint256 public noticePeriod; // advance notice period as seconds for reset uint256 constant MAX_INT = 2**256 - 1; event SignersUpdated(address[] _signers, uint256[] _powers); event ResetNotification(uint256 resetTime); /** * @notice Verifies that a message is signed by a quorum among the signers * The sigs must be sorted by signer addresses in ascending order. * @param _msg signed message * @param _sigs list of signatures sorted by signer addresses * @param _signers sorted list of current signers * @param _powers powers of current signers */ function verifySigs( bytes memory _msg, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) public view override { bytes32 h = keccak256(abi.encodePacked(_signers, _powers)); // require(ssHash == h, "Mismatch current signers"); _verifySignedPowers(keccak256(_msg).toEthSignedMessageHash(), _sigs, _signers, _powers); } /** * @notice Update new signers. * @param _newSigners sorted list of new signers * @param _curPowers powers of new signers * @param _sigs list of signatures sorted by signer addresses * @param _curSigners sorted list of current signers * @param _curPowers powers of current signers */ function updateSigners( uint256 _triggerTime, address[] calldata _newSigners, uint256[] calldata _newPowers, bytes[] calldata _sigs, address[] calldata _curSigners, uint256[] calldata _curPowers ) external { // use trigger time for nonce protection, must be ascending require(_triggerTime > triggerTime, "Trigger time is not increasing"); // make sure triggerTime is not too large, as it cannot be decreased once set require(_triggerTime < block.timestamp + 3600, "Trigger time is too large"); bytes32 domain = keccak256(abi.encodePacked(block.chainid, address(this), "UpdateSigners")); verifySigs(abi.encodePacked(domain, _triggerTime, _newSigners, _newPowers), _sigs, _curSigners, _curPowers); _updateSigners(_newSigners, _newPowers); triggerTime = _triggerTime; } /** * @notice reset signers, only used for init setup and emergency recovery */ function resetSigners(address[] calldata _signers, uint256[] calldata _powers) external onlyOwner { require(block.timestamp > resetTime, "not reach reset time"); resetTime = MAX_INT; _updateSigners(_signers, _powers); } function notifyResetSigners() external onlyOwner { resetTime = block.timestamp + noticePeriod; emit ResetNotification(resetTime); } function increaseNoticePeriod(uint256 period) external onlyOwner { require(period > noticePeriod, "notice period can only be increased"); noticePeriod = period; } // separate from verifySigs func to avoid "stack too deep" issue function _verifySignedPowers( bytes32 _hash, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) private pure { require(_signers.length == _powers.length, "signers and powers length not match"); uint256 totalPower; // sum of all signer.power for (uint256 i = 0; i < _signers.length; i++) { totalPower += _powers[i]; } uint256 quorum = (totalPower * 2) / 3 + 1; uint256 signedPower; // sum of signer powers who are in sigs address prev = address(0); uint256 index = 0; for (uint256 i = 0; i < _sigs.length; i++) { address signer = _hash.recover(_sigs[i]); require(signer > prev, "signers not in ascending order"); prev = signer; // now find match signer add its power while (signer > _signers[index]) { index += 1; require(index < _signers.length, "signer not found"); } if (signer == _signers[index]) { signedPower += _powers[index]; } if (signedPower >= quorum) { // return early to save gas return; } } revert("quorum not reached"); } function _updateSigners(address[] calldata _signers, uint256[] calldata _powers) private { require(_signers.length == _powers.length, "signers and powers length not match"); address prev = address(0); for (uint256 i = 0; i < _signers.length; i++) { require(_signers[i] > prev, "New signers not in ascending order"); prev = _signers[i]; } ssHash = keccak256(abi.encodePacked(_signers, _powers)); emit SignersUpdated(_signers, _powers); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import "@openzeppelin/contracts/access/Ownable.sol"; import "./interfaces/IBridge.sol"; import "./libraries/SafeERC20.sol"; import "./libraries/PbPool.sol"; import "./libraries/Signers.sol"; import "./libraries/OrderLib.sol"; import "./VerifySigEIP712.sol"; import "./interfaces/Structs.sol"; import "./libraries/AssetLib.sol"; interface IMultichainERC20 { function Swapout(uint256 amount, address bindaddr) external returns (bool); } contract Vault is Ownable, Signers, VerifySigEIP712 { using SafeERC20 for IERC20; IERC20 private constant NATIVE_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); //ETH chain address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address public ROUTER; address public CBRIDGE; address private dev; uint256 feePercent = 5; mapping(address => mapping(uint64 => BridgeInfo)) public userBridgeInfo; mapping(bytes32 => BridgeInfo) public transferInfo; mapping(bytes32 => bool) public transfers; mapping(address => address) public anyTokenAddress; mapping(address => bool) public allowedRouter; event Swap(address user, address srcToken, address toToken, uint256 amount, uint256 returnAmount); event Bridge(address user, uint64 chainId, address dstToken, uint256 amount, uint64 nonce, bytes32 transferId, string bridge); event Relayswap(address receiver, address toToken, uint256 returnAmount); receive() external payable {} constructor(address router, address cbridge) { ROUTER = router; CBRIDGE = cbridge; } function initMultichain(address[] calldata routers) external { require(msg.sender == dev || msg.sender == owner()); uint256 len = routers.length; for (uint256 i; i < len; ) { if (routers[i] == address(0)) { revert(); } allowedRouter[routers[i]] = true; unchecked { ++i; } } } function updateAddressMapping(AnyMapping[] calldata mappings) external { require(msg.sender == dev || msg.sender == owner()); for (uint64 i; i < mappings.length; i++) { anyTokenAddress[mappings[i].tokenAddress] = mappings[i].anyTokenAddress; } } function cBridge(CBridgeDescription calldata bDesc) external payable { bool isNotNative = !_isNative(IERC20(bDesc.srcToken)); if (isNotNative) { IERC20(bDesc.srcToken).safeTransferFrom(msg.sender, address(this), bDesc.amount); } _cBridgeStart(bDesc.amount, bDesc); } function multiChainBridge(MultiChainDescription calldata mDesc) public payable { bool isNative = !_isNative(IERC20(mDesc.srcToken)); if (isNative) { IERC20(mDesc.srcToken).safeTransferFrom(msg.sender, address(this), mDesc.amount); } _multiChainBridgeStart(mDesc.amount, mDesc); } function swapRouter(SwapData calldata _swap) external payable { _isNativeDeposit(IERC20(_swap.srcToken), _swap.amount); _userSwapStart(_swap); } function swapCBridge(SwapData calldata _swap, CBridgeDescription calldata bDesc) external payable { SwapData calldata swapData = _swap; _isNativeDeposit(IERC20(swapData.srcToken), swapData.amount); uint256 dstAmount = _swapStart(swapData); _cBridgeStart(dstAmount, bDesc); } function swapMultichain(SwapData calldata _swap, MultiChainDescription calldata mDesc) external payable { SwapData calldata swapData = _swap; _isNativeDeposit(IERC20(swapData.srcToken), swapData.amount); uint256 dstAmount = _swapStart(swapData); if (!allowedRouter[mDesc.router]) revert(); _multiChainBridgeStart(dstAmount, mDesc); } function _fee(address dstToken, uint256 dstAmount) private returns (uint256 returnAmount) { uint256 fee = (dstAmount * feePercent) / 10000; returnAmount = dstAmount - fee; if (fee > 0) { if (!_isNative(IERC20(dstToken))) { IERC20(dstToken).safeTransfer(owner(), fee); } else { _safeNativeTransfer(owner(), fee); } } } function _swapStart(SwapData calldata swapData) private returns (uint256 dstAmount) { SwapData calldata swap = swapData; bool isNative = _isNative(IERC20(swap.srcToken)); uint256 initDstTokenBalance = AssetLib.getBalance(swap.dstToken); (bool succ, ) = address(ROUTER).call{value: isNative ? swap.amount : 0}(swap.callData); if (succ) { uint256 dstTokenBalance = AssetLib.getBalance(swap.dstToken); dstAmount = dstTokenBalance > initDstTokenBalance ? dstTokenBalance - initDstTokenBalance : dstTokenBalance; emit Swap(swap.user, swap.srcToken, swap.dstToken, swap.amount, dstAmount); } else { revert(); } } function _userSwapStart(SwapData calldata swapData) private returns (uint256 dstAmount) { SwapData calldata swap = swapData; bool isNative = _isNative(IERC20(swap.srcToken)); uint256 initDstTokenBalance = AssetLib.userBalance(swap.user, swap.dstToken); (bool succ, ) = address(ROUTER).call{value: isNative ? swap.amount : 0}(swap.callData); if (succ) { uint256 dstTokenBalance = AssetLib.userBalance(swap.user, swap.dstToken); dstAmount = dstTokenBalance > initDstTokenBalance ? dstTokenBalance - initDstTokenBalance : dstTokenBalance; emit Swap(swap.user, swap.srcToken, swap.dstToken, swap.amount, dstAmount); } else { revert(); } } function relaySwapRouter( SwapData calldata _swap, // => Input calldata _sigCollect, bytes[] memory signature ) external onlyOwner { SwapData calldata swap = _swap; Input calldata sig = _sigCollect; require(sig.userAddress == swap.user && sig.amount - sig.gasFee == swap.amount && sig.toTokenAddress == swap.dstToken); relaySig(sig, signature); require(transfers[sig.txHash] == false, "safeTransfer exists"); // 추가 transfers[sig.txHash] = true; // 추가 bool isNotNative = !_isNative(IERC20(sig.fromTokenAddress)); uint256 fromAmount = sig.amount - sig.gasFee; if (isNotNative) { IERC20(sig.fromTokenAddress).safeApprove(ROUTER, fromAmount); //desc.amount 는 amount - gasFee if (sig.gasFee > 0) IERC20(sig.fromTokenAddress).safeTransfer(owner(), sig.gasFee); } else { if (sig.gasFee > 0) _safeNativeTransfer(owner(), sig.gasFee); } uint256 dstAmount = _swapStart(swap); emit Relayswap(sig.userAddress, sig.toTokenAddress, dstAmount); } // delete function EmergencyWithdraw(address _tokenAddress, uint256 amount) public onlyOwner { bool isNotNative = !_isNative(IERC20(_tokenAddress)); if (isNotNative) { IERC20(_tokenAddress).safeTransfer(owner(), amount); } else { _safeNativeTransfer(owner(), amount); } } function sigWithdraw( bytes calldata _wdmsg, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external { IBridge(CBRIDGE).withdraw(_wdmsg, _sigs, _signers, _powers); bytes32 domain = keccak256(abi.encodePacked(block.chainid, CBRIDGE, "WithdrawMsg")); verifySigs(abi.encodePacked(domain, _wdmsg), _sigs, _signers, _powers); PbPool.WithdrawMsg memory wdmsg = PbPool.decWithdrawMsg(_wdmsg); BridgeInfo memory tif = transferInfo[wdmsg.refid]; bool isNotNative = !_isNative(IERC20(tif.dstToken)); if (isNotNative) { IERC20(tif.dstToken).safeTransfer(tif.user, tif.amount); } else { _safeNativeTransfer(tif.user, tif.amount); } } function setRouterBridge(address _router, address _cbridge) public { require(msg.sender == dev || msg.sender == owner()); ROUTER = _router; CBRIDGE = _cbridge; } function setFeePercent(uint256 percent) external { require(msg.sender == dev || msg.sender == owner()); feePercent = percent; } function _isNative(IERC20 token_) internal pure returns (bool) { return (token_ == NATIVE_ADDRESS); } function _isNativeDeposit(IERC20 _token, uint256 _amount) internal returns (bool isNotNative) { isNotNative = !_isNative(_token); if (isNotNative) { IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount); IERC20(_token).safeApprove(ROUTER, _amount); } } function _cBridgeStart(uint256 dstAmount, CBridgeDescription calldata bdesc) internal { CBridgeDescription memory bDesc = bdesc; dstAmount = _fee(bDesc.srcToken, dstAmount); bool isNotNative = !_isNative(IERC20(bDesc.srcToken)); if (isNotNative) { IERC20(bDesc.srcToken).safeApprove(CBRIDGE, dstAmount); IBridge(CBRIDGE).send(bDesc.receiver, bDesc.srcToken, dstAmount, bDesc.dstChainId, bDesc.nonce, bDesc.maxSlippage); } else { IBridge(CBRIDGE).sendNative{value: dstAmount}(bDesc.receiver, dstAmount, bDesc.dstChainId, bDesc.nonce, bDesc.maxSlippage); bDesc.srcToken = WETH; } bytes32 transferId = keccak256( abi.encodePacked(address(this), bDesc.receiver, bDesc.srcToken, dstAmount, bDesc.dstChainId, bDesc.nonce, uint64(block.chainid)) ); BridgeInfo memory tif = transferInfo[transferId]; require(tif.nonce == 0, " PLEXUS: transferId already exists. Check the nonce."); tif.dstToken = bDesc.srcToken; tif.chainId = bDesc.dstChainId; tif.amount = dstAmount; tif.user = msg.sender; tif.nonce = bDesc.nonce; tif.bridge = "CBridge"; transferInfo[transferId] = tif; emit Bridge(tif.user, tif.chainId, tif.dstToken, tif.amount, tif.nonce, transferId, tif.bridge); } function _multiChainBridgeStart(uint256 dstAmount, MultiChainDescription calldata mDesc) internal { address anyToken = anyTokenAddress[mDesc.srcToken]; dstAmount = _fee(mDesc.srcToken, dstAmount); if (mDesc.router == anyToken) { IMultichainERC20(anyToken).Swapout(dstAmount, mDesc.receiver); } else { if (_isNative(IERC20(mDesc.srcToken))) { IBridge(mDesc.router).anySwapOutNative{value: dstAmount}(anyToken, mDesc.receiver, mDesc.dstChainId); } else { IERC20(mDesc.srcToken).safeApprove(mDesc.router, dstAmount); IBridge(mDesc.router).anySwapOutUnderlying( anyToken != address(0) ? anyToken : mDesc.srcToken, mDesc.receiver, dstAmount, mDesc.dstChainId ); } } bytes32 transferId = keccak256( abi.encodePacked(address(this), mDesc.receiver, mDesc.srcToken, dstAmount, mDesc.dstChainId, mDesc.nonce, uint64(block.chainid)) ); BridgeInfo memory tif = transferInfo[transferId]; require(tif.nonce == 0, " PLEXUS: transferId already exists. Check the nonce."); tif.dstToken = mDesc.srcToken; tif.chainId = mDesc.dstChainId; tif.amount = dstAmount; tif.user = msg.sender; tif.nonce = mDesc.nonce; tif.bridge = "MultiChainBridge"; transferInfo[transferId] = tif; emit Bridge(tif.user, tif.chainId, tif.dstToken, tif.amount, tif.nonce, transferId, tif.bridge); } function _safeNativeTransfer(address to_, uint256 amount_) private { (bool sent, ) = to_.call{value: amount_}(""); require(sent, "Safe safeTransfer fail"); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract VerifySigEIP712 is EIP712("Plexus", "1"), Ownable { address[] public ownerList; struct Input { address fromTokenAddress; address toTokenAddress; uint256 amount; // ToChain넘어와서 브릿지가 볼트로 보내줄때 그 수량. ( 수루료 빠지기 전 ) uint256 gasFee; // 가스비를 확인해서 그만큼의 token수량 address userAddress; bytes32 txHash; } bytes32 private constant SWAP_TYPEHASH = keccak256("Input(address fromTokenAddress,address toTokenAddress,uint256 amount,uint256 gasFee,address userAddress,bytes32 txHash)"); function setSigner(address[] memory _owner) public onlyOwner { for (uint256 i = 0; i < _owner.length; i++) { ownerList.push(_owner[i]); } } function relaySig(Input memory _swapData, bytes[] memory signature) public view returns (bool) { uint256 CheckCount; Input memory inputData = _swapData; for (uint256 i = 0; i < signature.length; i++) { bytes32 digest = _hashTypedDataV4( keccak256( abi.encode( SWAP_TYPEHASH, inputData.fromTokenAddress, inputData.toTokenAddress, inputData.amount, inputData.gasFee, inputData.userAddress, inputData.txHash ) ) ); (bytes32 r, bytes32 s, uint8 v) = splitSignature(signature[i]); address signer = ECDSA.recover(digest, v, r, s); if (signer == ownerList[i]) { CheckCount++; } } if (CheckCount == signature.length) return true; else { revert("not match"); } } // 시그니쳐 넣으면 r s v 찢어주는 함수 function splitSignature(bytes memory sig) public pure returns ( bytes32 r, bytes32 s, uint8 v ) { require(sig.length == 65, "invalid signature length"); assembly { // first 32 bytes, after the length prefix r := mload(add(sig, 32)) // second 32 bytes s := mload(add(sig, 64)) // final byte (first byte of the next 32 bytes) v := byte(0, mload(add(sig, 96))) } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"cbridge","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"address","name":"dstToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"nonce","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"transferId","type":"bytes32"},{"indexed":false,"internalType":"string","name":"bridge","type":"string"}],"name":"Bridge","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":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"toToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"returnAmount","type":"uint256"}],"name":"Relayswap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"resetTime","type":"uint256"}],"name":"ResetNotification","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"_signers","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"SignersUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"srcToken","type":"address"},{"indexed":false,"internalType":"address","name":"toToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"returnAmount","type":"uint256"}],"name":"Swap","type":"event"},{"inputs":[],"name":"CBRIDGE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ROUTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowedRouter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"anyTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"uint32","name":"maxSlippage","type":"uint32"}],"internalType":"struct CBridgeDescription","name":"bDesc","type":"tuple"}],"name":"cBridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"period","type":"uint256"}],"name":"increaseNoticePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"routers","type":"address[]"}],"name":"initMultichain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"router","type":"address"}],"internalType":"struct MultiChainDescription","name":"mDesc","type":"tuple"}],"name":"multiChainBridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"noticePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"notifyResetSigners","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownerList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"gasFee","type":"uint256"},{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes32","name":"txHash","type":"bytes32"}],"internalType":"struct VerifySigEIP712.Input","name":"_swapData","type":"tuple"},{"internalType":"bytes[]","name":"signature","type":"bytes[]"}],"name":"relaySig","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct SwapData","name":"_swap","type":"tuple"},{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"gasFee","type":"uint256"},{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes32","name":"txHash","type":"bytes32"}],"internalType":"struct VerifySigEIP712.Input","name":"_sigCollect","type":"tuple"},{"internalType":"bytes[]","name":"signature","type":"bytes[]"}],"name":"relaySwapRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"resetSigners","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resetTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"percent","type":"uint256"}],"name":"setFeePercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_cbridge","type":"address"}],"name":"setRouterBridge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_owner","type":"address[]"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_wdmsg","type":"bytes"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"sigWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"splitSignature","outputs":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"ssHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct SwapData","name":"_swap","type":"tuple"},{"components":[{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"uint32","name":"maxSlippage","type":"uint32"}],"internalType":"struct CBridgeDescription","name":"bDesc","type":"tuple"}],"name":"swapCBridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct SwapData","name":"_swap","type":"tuple"},{"components":[{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"router","type":"address"}],"internalType":"struct MultiChainDescription","name":"mDesc","type":"tuple"}],"name":"swapMultichain","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct SwapData","name":"_swap","type":"tuple"}],"name":"swapRouter","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"transferInfo","outputs":[{"internalType":"string","name":"bridge","type":"string"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"transfers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"triggerTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"anyTokenAddress","type":"address"}],"internalType":"struct AnyMapping[]","name":"mappings","type":"tuple[]"}],"name":"updateAddressMapping","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_triggerTime","type":"uint256"},{"internalType":"address[]","name":"_newSigners","type":"address[]"},{"internalType":"uint256[]","name":"_newPowers","type":"uint256[]"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"_curSigners","type":"address[]"},{"internalType":"uint256[]","name":"_curPowers","type":"uint256[]"}],"name":"updateSigners","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"userBridgeInfo","outputs":[{"internalType":"string","name":"bridge","type":"string"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_msg","type":"bytes"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"verifySigs","outputs":[],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
61014060405260056009553480156200001757600080fd5b5060405162004b5038038062004b508339810160408190526200003a91620001d8565b6040805180820182526006815265506c6578757360d01b6020808301918252835180850190945260018452603160f81b908401528151902060e08190527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66101008190524660a0529192917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620001168184846040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b6080523060c0526101205250620001399250620001339150503390565b6200016b565b600680546001600160a01b039384166001600160a01b0319918216179091556007805492909316911617905562000210565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b0381168114620001d357600080fd5b919050565b60008060408385031215620001ec57600080fd5b620001f783620001bb565b91506200020760208401620001bb565b90509250929050565b60805160a05160c05160e05161010051610120516148f06200026060003960006132d101526000613320015260006132fb015260006132540152600061327e015260006132a801526148f06000f3fe6080604052600436106102085760003560e01c80638da5cb5b11610118578063c93341ec116100a0578063d1f906d11161006f578063d1f906d1146105e0578063def79ab514610616578063e2d7ddbb14610636578063f20c922a14610656578063f2fde38b1461067657600080fd5b8063c93341ec1461056a578063cc818ad11461058a578063cebaf8a9146105aa578063d0790da9146105ca57600080fd5b8063a7bdf45a116100e7578063a7bdf45a146104d2578063acf64c43146104f2578063b35ebdc314610524578063ba2cb25c14610537578063bedf153f1461055757600080fd5b80638da5cb5b1461044d5780639b14d4c61461046b578063a3142fae14610481578063a7bb58031461049457600080fd5b80635fafa99d1161019b578063715018a61161016a578063715018a6146103b85780637a79a608146103cd5780637b25503a146103ed5780637ce3489b1461040d5780638c4f354b1461042d57600080fd5b80635fafa99d1461034f57806360a614ab1461036f57806365a114f114610382578063682dbc221461039857600080fd5b806332fe7b26116101d757806332fe7b26146102b0578063370fb47b146102e85780633c64f04b1461030c578063530ff3871461033c57600080fd5b8063223796f71461021457806322ee82db1461023657806325c38b9f1461025657806330ca07d51461026b57600080fd5b3661020f57005b600080fd5b34801561022057600080fd5b5061023461022f3660046138f2565b610696565b005b34801561024257600080fd5b50610234610251366004613983565b610921565b34801561026257600080fd5b5061023461099a565b34801561027757600080fd5b5061029b610286366004613a0f565b600e6020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156102bc57600080fd5b506006546102d0906001600160a01b031681565b6040516001600160a01b0390911681526020016102a7565b3480156102f457600080fd5b506102fe60025481565b6040519081526020016102a7565b34801561031857600080fd5b5061029b610327366004613a2a565b600c6020526000908152604090205460ff1681565b61023461034a366004613a43565b6109e9565b34801561035b57600080fd5b5061023461036a366004613a91565b610a5f565b61023461037d366004613a43565b610ac1565b34801561038e57600080fd5b506102fe60035481565b3480156103a457600080fd5b506102346103b3366004613aff565b610aed565b3480156103c457600080fd5b50610234610b94565b3480156103d957600080fd5b506102346103e8366004613bbd565b610ba8565b3480156103f957600080fd5b50610234610408366004613cab565b610e64565b34801561041957600080fd5b50610234610428366004613a2a565b610f4f565b34801561043957600080fd5b50610234610448366004613d1f565b610f80565b34801561045957600080fd5b506000546001600160a01b03166102d0565b34801561047757600080fd5b506102fe60045481565b61023461048f366004613d49565b610fda565b3480156104a057600080fd5b506104b46104af366004613d7d565b610ff7565b60408051938452602084019290925260ff16908201526060016102a7565b3480156104de57600080fd5b506102346104ed366004613db1565b61106b565b3480156104fe57600080fd5b5061051261050d366004613a2a565b6110cd565b6040516102a796959493929190613e6c565b610234610532366004613ec3565b6111a4565b34801561054357600080fd5b50610234610552366004613edf565b6111f4565b610234610565366004613ec3565b611335565b34801561057657600080fd5b5061029b61058536600461406a565b611374565b34801561059657600080fd5b506102346105a53660046140b8565b611513565b3480156105b657600080fd5b506105126105c5366004614110565b6115e4565b3480156105d657600080fd5b506102fe60015481565b3480156105ec57600080fd5b506102d06105fb366004613a0f565b600d602052600090815260409020546001600160a01b031681565b34801561062257600080fd5b506102d0610631366004613a2a565b61160a565b34801561064257600080fd5b506007546102d0906001600160a01b031681565b34801561066257600080fd5b50610234610671366004613a2a565b611634565b34801561068257600080fd5b50610234610691366004613a0f565b61169e565b61069e611717565b82826106ad6020830183613a0f565b6001600160a01b03166106c660a0830160808401613a0f565b6001600160a01b03161480156106f257508160600135816060013582604001356106f09190614150565b145b801561072d57506107096060830160408401613a0f565b6001600160a01b03166107226040830160208401613a0f565b6001600160a01b0316145b61073657600080fd5b61074e61074836839003830183614163565b84611374565b5060a08101356000908152600c602052604090205460ff16156107ae5760405162461bcd60e51b8152602060048201526013602482015272736166655472616e736665722065786973747360681b60448201526064015b60405180910390fd5b60a08101356000908152600c602090815260408220805460ff191660011790556107e3906107de90840184613a0f565b611771565b15905060006107fa60608401356040850135614150565b9050811561087657600654610830906001600160a01b0316826108206020870187613a0f565b6001600160a01b03169190611793565b6060830135156108715761087161084f6000546001600160a01b031690565b60608501356108616020870187613a0f565b6001600160a01b031691906118db565b61089f565b60608301351561089f5761089f6108956000546001600160a01b031690565b846060013561190b565b60006108aa856119a7565b90507fdef08483254d44ac41909d1188fb7c523c398e22edeab0e1d9c941a98629b5d36108dd60a0860160808701613a0f565b6108ed6040870160208801613a0f565b604080516001600160a01b039384168152929091166020830152810183905260600160405180910390a15050505050505050565b610929611717565b60005b81518110156109965760058282815181106109495761094961417f565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790558061098e81614195565b91505061092c565b5050565b6109a2611717565b6004546109af90426141ae565b60038190556040519081527f68e825132f7d4bc837dea2d64ac9fc19912bf0224b67f9317d8f1a917f5304a19060200160405180910390a1565b81610a076109fd6040830160208401613a0f565b8260600135611b28565b506000610a13826119a7565b9050600e6000610a2960c0860160a08701613a0f565b6001600160a01b0316815260208101919091526040016000205460ff16610a4f57600080fd5b610a598184611b6b565b50505050565b610a67611717565b6000610a7283611771565b1590508015610aa657610aa1610a906000546001600160a01b031690565b6001600160a01b03851690846118db565b505050565b610aa1610abb6000546001600160a01b031690565b8361190b565b81610ad56109fd6040830160208401613a0f565b506000610ae1826119a7565b9050610a59818461214b565b600084848484604051602001610b069493929190614229565b604051602081830303815290604052805190602001209050610b8a610b7f89805190602001206040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b8888888888886125c5565b5050505050505050565b610b9c611717565b610ba660006128a6565b565b600754604051630144352560e71b81526001600160a01b039091169063a21a928090610be6908b908b908b908b908b908b908b908b906004016142ec565b600060405180830381600087803b158015610c0057600080fd5b505af1158015610c14573d6000803e3d6000fd5b505060075460405160009350610c63925046916001600160a01b03169060200191825260601b6001600160601b03191660208201526a57697468647261774d736760a81b6034820152603f0190565b604051602081830303815290604052805190602001209050610cad818a8a604051602001610c93939291906143c9565b604051602081830303815290604052888888888888610aed565b6000610cee8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506128f692505050565b90506000600b60008360a0015181526020019081526020016000206040518060c0016040529081600082018054610d24906143e3565b80601f0160208091040260200160405190810160405280929190818152602001828054610d50906143e3565b8015610d9d5780601f10610d7257610100808354040283529160200191610d9d565b820191906000526020600020905b815481529060010190602001808311610d8057829003601f168201915b505050918352505060018201546001600160a01b038082166020808501919091526001600160401b03600160a01b938490048116604086015260028601546060860152600390950154918216608085015291900490921660a090910152810151909150600090610e0c90611771565b1590508015610e4457610e3f8260800151836060015184602001516001600160a01b03166118db9092919063ffffffff16565b610e56565b610e568260800151836060015161190b565b505050505050505050505050565b6008546001600160a01b0316331480610e8757506000546001600160a01b031633145b610e9057600080fd5b60005b6001600160401b038116821115610aa1578282826001600160401b0316818110610ebf57610ebf61417f565b9050604002016020016020810190610ed79190613a0f565b600d60008585856001600160401b0316818110610ef657610ef661417f565b610f0c9260206040909202019081019150613a0f565b6001600160a01b039081168252602082019290925260400160002080546001600160a01b0319169290911691909117905580610f4781614417565b915050610e93565b6008546001600160a01b0316331480610f7257506000546001600160a01b031633145b610f7b57600080fd5b600955565b6008546001600160a01b0316331480610fa357506000546001600160a01b031633145b610fac57600080fd5b600680546001600160a01b039384166001600160a01b03199182161790915560078054929093169116179055565b610fed6109fd6040830160208401613a0f565b5061099681612a4e565b6000806000835160411461104d5760405162461bcd60e51b815260206004820152601860248201527f696e76616c6964207369676e6174757265206c656e677468000000000000000060448201526064016107a5565b50505060208101516040820151606090920151909260009190911a90565b611073611717565b60035442116110bb5760405162461bcd60e51b81526020600482015260146024820152736e6f742072656163682072657365742074696d6560601b60448201526064016107a5565b600019600355610a5984848484612b3b565b600b602052600090815260409020805481906110e8906143e3565b80601f0160208091040260200160405190810160405280929190818152602001828054611114906143e3565b80156111615780601f1061113657610100808354040283529160200191611161565b820191906000526020600020905b81548152906001019060200180831161114457829003601f168201915b5050506001840154600285015460039095015493946001600160a01b03808316956001600160401b03600160a01b94859004811696509294509081169290041686565b60006111b66107de6020840184613a0f565b15905080156111e6576111e63330602085018035906111d59087613a0f565b6001600160a01b0316929190612c9a565b610996826020013583611b6b565b6002548b116112455760405162461bcd60e51b815260206004820152601e60248201527f547269676765722074696d65206973206e6f7420696e6372656173696e67000060448201526064016107a5565b61125142610e106141ae565b8b1061129f5760405162461bcd60e51b815260206004820152601960248201527f547269676765722074696d6520697320746f6f206c617267650000000000000060448201526064016107a5565b600046306040516020016112e092919091825260601b6001600160601b03191660208201526c5570646174655369676e65727360981b603482015260410190565b604051602081830303815290604052805190602001209050611316818d8d8d8d8d604051602001610c939695949392919061443d565b6113228b8b8b8b612b3b565b5050506002989098555050505050505050565b60006113476107de6020840184613a0f565b1590508015611366576113663330602085018035906111d59087613a0f565b61099682602001358361214b565b60008083815b84518110156114c557600061142e7f23708f9a7a9c68b1a6cd4e9244f4b17e38b50b4448142b6ba580ab9052fe7d1e846000015185602001518660400151876060015188608001518960a0015160405160200161141397969594939291909687526001600160a01b03958616602088015293851660408701526060860192909252608085015290911660a083015260c082015260e00190565b60405160208183030381529060405280519060200120612cd2565b9050600080600061145789868151811061144a5761144a61417f565b6020026020010151610ff7565b925092509250600061146b85838686612d20565b9050600586815481106114805761148061417f565b6000918252602090912001546001600160a01b03908116908216036114ad57876114a981614195565b9850505b505050505080806114bd90614195565b91505061137a565b50835182036114d95760019250505061150d565b60405162461bcd60e51b81526020600482015260096024820152680dcdee840dac2e8c6d60bb1b60448201526064016107a5565b92915050565b6008546001600160a01b031633148061153657506000546001600160a01b031633145b61153f57600080fd5b8060005b81811015610a5957600084848381811061155f5761155f61417f565b90506020020160208101906115749190613a0f565b6001600160a01b03160361158757600080fd5b6001600e600086868581811061159f5761159f61417f565b90506020020160208101906115b49190613a0f565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055600101611543565b600a6020908152600092835260408084209091529082529020805481906110e8906143e3565b6005818154811061161a57600080fd5b6000918252602090912001546001600160a01b0316905081565b61163c611717565b60045481116116995760405162461bcd60e51b815260206004820152602360248201527f6e6f7469636520706572696f642063616e206f6e6c7920626520696e637265616044820152621cd95960ea1b60648201526084016107a5565b600455565b6116a6611717565b6001600160a01b03811661170b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016107a5565b611714816128a6565b50565b6000546001600160a01b03163314610ba65760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107a5565b6001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1490565b80158061180d5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156117e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180b9190614465565b155b6118785760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60648201526084016107a5565b6040516001600160a01b038316602482015260448101829052610aa190849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612d48565b6040516001600160a01b038316602482015260448101829052610aa190849063a9059cbb60e01b906064016118a4565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611958576040519150601f19603f3d011682016040523d82523d6000602084013e61195d565b606091505b5050905080610aa15760405162461bcd60e51b815260206004820152601660248201527514d85999481cd85999551c985b9cd9995c8819985a5b60521b60448201526064016107a5565b600081816119be6107de6040840160208501613a0f565b905060006119da6119d56060850160408601613a0f565b612e1a565b6006549091506000906001600160a01b0316836119f85760006119fe565b84606001355b611a0b608087018761447e565b604051611a199291906144c4565b60006040518083038185875af1925050503d8060008114611a56576040519150601f19603f3d011682016040523d82523d6000602084013e611a5b565b606091505b50509050801561020f576000611a7a6119d56060870160408801613a0f565b9050828111611a895780611a93565b611a938382614150565b95507fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e46062611ac36020870187613a0f565b611ad36040880160208901613a0f565b611ae36060890160408a01613a0f565b604080516001600160a01b0394851681529284166020840152921681830152606088810135908201526080810189905290519081900360a00190a15050505050919050565b6000611b3383611771565b159050801561150d57611b516001600160a01b038416333085612c9a565b60065461150d906001600160a01b03858116911684611793565b6000600d81611b7d6020850185613a0f565b6001600160a01b039081168252602080830193909352604090910160002054169150611bb590611baf90840184613a0f565b84612eb4565b92506001600160a01b038116611bd160c0840160a08501613a0f565b6001600160a01b031603611c75576001600160a01b03811663628d6cba84611bff6060860160408701613a0f565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af1158015611c4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6f91906144d4565b50611e33565b611c856107de6020840184613a0f565b15611d3f57611c9a60c0830160a08401613a0f565b6001600160a01b031663a5e565718483611cba6060870160408801613a0f565b611cca60808801606089016144f6565b6040516001600160e01b031960e087901b1681526001600160a01b0393841660048201529290911660248301526001600160401b031660448201526064016000604051808303818588803b158015611d2157600080fd5b505af1158015611d35573d6000803e3d6000fd5b5050505050611e33565b611d60611d5260c0840160a08501613a0f565b846108206020860186613a0f565b611d7060c0830160a08401613a0f565b6001600160a01b039081169063edbdf5e2908316611d9a57611d956020850185613a0f565b611d9c565b825b611dac6060860160408701613a0f565b86611dbd60808801606089016144f6565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015293909216602484015260448301526001600160401b03166064820152608401600060405180830381600087803b158015611e1a57600080fd5b505af1158015611e2e573d6000803e3d6000fd5b505050505b600030611e466060850160408601613a0f565b611e536020860186613a0f565b86611e6460808801606089016144f6565b611e7460a0890160808a016144f6565b46604051602001611e8b9796959493929190614511565b6040516020818303038152906040528051906020012090506000600b60008381526020019081526020016000206040518060c0016040529081600082018054611ed3906143e3565b80601f0160208091040260200160405190810160405280929190818152602001828054611eff906143e3565b8015611f4c5780601f10611f2157610100808354040283529160200191611f4c565b820191906000526020600020905b815481529060010190602001808311611f2f57829003601f168201915b505050918352505060018201546001600160a01b0380821660208401526001600160401b03600160a01b928390048116604085015260028501546060850152600390940154908116608084015204821660a0918201528201519192501615611fc65760405162461bcd60e51b81526004016107a590614570565b611fd36020850185613a0f565b6001600160a01b03166020820152611ff160808501606086016144f6565b6001600160401b0316604082015260608101859052336080808301919091526120209060a086019086016144f6565b6001600160401b031660a0820152604080518082018252601081526f4d756c7469436861696e42726964676560801b6020808301919091529083526000848152600b90915220815182919081906120779082614612565b506020828101516001830180546040808701516001600160401b03908116600160a01b9081026001600160e01b03199485166001600160a01b03978816171790945560608089015160028901556080808a01516003909901805460a09b8c01519094169096029290941697909516969096179590951790915585015185840151928601519186015194860151865194517f79f05c54adc8706b09eb1a59fd13fb4b47a6d47fa4c17d6905cc91c84471e1819661213c96939594939092918a91906146d1565b60405180910390a15050505050565b600061215c36839003830183614730565b905061216c816000015184612eb4565b9250600061217d8260000151611771565b159050801561224e5760075482516121a2916001600160a01b03918216911686611793565b60075460408381015184516060860151608087015160a0880151945163a5977fbb60e01b81526001600160a01b0394851660048201529284166024840152604483018a90526001600160401b03918216606484015216608482015263ffffffff90921660a48301529091169063a5977fbb9060c401600060405180830381600087803b15801561223157600080fd5b505af1158015612245573d6000803e3d6000fd5b50505050612306565b6007546040838101516060850151608086015160a08701519351633f2e5fc360e01b81526001600160a01b039384166004820152602481018a90526001600160401b0392831660448201529116606482015263ffffffff909216608483015290911690633f2e5fc390869060a4016000604051808303818588803b1580156122d557600080fd5b505af11580156122e9573d6000803e3d6000fd5b505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc285525050505b600030836040015184600001518786606001518760800151466040516020016123359796959493929190614511565b6040516020818303038152906040528051906020012090506000600b60008381526020019081526020016000206040518060c001604052908160008201805461237d906143e3565b80601f01602080910402602001604051908101604052809291908181526020018280546123a9906143e3565b80156123f65780601f106123cb576101008083540402835291602001916123f6565b820191906000526020600020905b8154815290600101906020018083116123d957829003601f168201915b505050918352505060018201546001600160a01b0380821660208401526001600160401b03600160a01b928390048116604085015260028501546060850152600390940154908116608084015204821660a09182015282015191925016156124705760405162461bcd60e51b81526004016107a590614570565b83516001600160a01b03166020808301919091526060808601516001600160401b03908116604080860191909152918401899052336080808601919091528701511660a08401528051808201825260078152664342726964676560c81b8184015283526000848152600b9092529020815182919081906124f09082614612565b506020828101516001830180546040808701516001600160401b03908116600160a01b9081026001600160e01b03199485166001600160a01b03978816171790945560608089015160028901556080808a01516003909901805460a09b8c01519094169096029290941697909516969096179590951790915585015185840151928601519186015194860151865194517f79f05c54adc8706b09eb1a59fd13fb4b47a6d47fa4c17d6905cc91c84471e181966125b596939594939092918a91906146d1565b60405180910390a1505050505050565b8281146125e45760405162461bcd60e51b81526004016107a5906147d2565b6000805b84811015612628578383828181106126025761260261417f565b905060200201358261261491906141ae565b91508061262081614195565b9150506125e8565b5060006003612638836002614815565b612642919061482c565b61264d9060016141ae565b905060008080805b8a81101561285f5760006126d88d8d848181106126745761267461417f565b9050602002810190612686919061447e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508f612f4090919063ffffffff16565b9050836001600160a01b0316816001600160a01b03161161273b5760405162461bcd60e51b815260206004820152601e60248201527f7369676e657273206e6f7420696e20617363656e64696e67206f72646572000060448201526064016107a5565b8093505b8a8a848181106127515761275161417f565b90506020020160208101906127669190613a0f565b6001600160a01b0316816001600160a01b031611156127d35761278a6001846141ae565b92508983106127ce5760405162461bcd60e51b815260206004820152601060248201526f1cda59db995c881b9bdd08199bdd5b9960821b60448201526064016107a5565b61273f565b8a8a848181106127e5576127e561417f565b90506020020160208101906127fa9190613a0f565b6001600160a01b0316816001600160a01b031603612839578888848181106128245761282461417f565b905060200201358561283691906141ae565b94505b85851061284c575050505050505061289d565b508061285781614195565b915050612655565b5060405162461bcd60e51b81526020600482015260126024820152711c5d5bdc9d5b481b9bdd081c995858da195960721b60448201526064016107a5565b50505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040805160c08101825260008082526020808301829052828401829052606083018290526080830182905260a0830182905283518085019094528184528301849052909190805b60208301515183511015612a465761295483612f64565b90925090508160010361297a5761296a83612f9e565b6001600160401b0316845261293d565b8160020361299e5761298b83612f9e565b6001600160401b0316602085015261293d565b816003036129ca576129b76129b284613019565b6130d5565b6001600160a01b0316604085015261293d565b816004036129f1576129de6129b284613019565b6001600160a01b0316606085015261293d565b81600503612a1457612a0a612a0584613019565b6130e0565b608085015261293d565b81600603612a3757612a2d612a2884613019565b613117565b60a085015261293d565b612a41838261312f565b61293d565b505050919050565b60008181612a656107de6040840160208501613a0f565b90506000612a8e612a796020850185613a0f565b612a896060860160408701613a0f565b61319f565b6006549091506000906001600160a01b031683612aac576000612ab2565b84606001355b612abf608087018761447e565b604051612acd9291906144c4565b60006040518083038185875af1925050503d8060008114612b0a576040519150601f19603f3d011682016040523d82523d6000602084013e612b0f565b606091505b50509050801561020f576000611a7a612b2b6020870187613a0f565b612a896060880160408901613a0f565b828114612b5a5760405162461bcd60e51b81526004016107a5906147d2565b6000805b84811015612c3357816001600160a01b0316868683818110612b8257612b8261417f565b9050602002016020810190612b979190613a0f565b6001600160a01b031611612bf85760405162461bcd60e51b815260206004820152602260248201527f4e6577207369676e657273206e6f7420696e20617363656e64696e67206f726460448201526132b960f11b60648201526084016107a5565b858582818110612c0a57612c0a61417f565b9050602002016020810190612c1f9190613a0f565b915080612c2b81614195565b915050612b5e565b5084848484604051602001612c4b9493929190614229565b60408051601f198184030181529082905280516020909101206001557ff126123539a68393c55697f617e7d1148e371988daed246c2f41da99965a23f89061213c90879087908790879061484e565b6040516001600160a01b0380851660248301528316604482015260648101829052610a599085906323b872dd60e01b906084016118a4565b600061150d612cdf613247565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000612d318787878761336e565b91509150612d3e81613432565b5095945050505050565b6000612d9d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661357c9092919063ffffffff16565b805190915015610aa15780806020019051810190612dbb91906144d4565b610aa15760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016107a5565b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14612ead576040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015612e84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea89190614465565b61150d565b4792915050565b60008061271060095484612ec89190614815565b612ed2919061482c565b9050612ede8184614150565b91508015612f3957612eef84611771565b612f1e57612f19612f086000546001600160a01b031690565b6001600160a01b03861690836118db565b612f39565b612f39612f336000546001600160a01b031690565b8261190b565b5092915050565b6000806000612f4f8585613593565b91509150612f5c81613432565b509392505050565b6000806000612f7284612f9e565b9050612f7f60088261482c565b9250806007166005811115612f9657612f96614875565b915050915091565b602080820151825181019091015160009182805b600a81101561020f5783811a9150612fcb816007614815565b82607f16901b851794508160801660000361300757612feb8160016141ae565b86518790612ffa9083906141ae565b9052509395945050505050565b8061301181614195565b915050612fb2565b6060600061302683612f9e565b9050600081846000015161303a91906141ae565b905083602001515181111561304e57600080fd5b816001600160401b038111156130665761306661378b565b6040519080825280601f01601f191660200182016040528015613090576020820181803683370190505b50602080860151865192955091818601919083010160005b858110156130ca5781810151838201526130c36020826141ae565b90506130a8565b505050935250919050565b600061150d826135d8565b60006020825111156130f157600080fd5b60208201519050815160206131069190614150565b613111906008614815565b1c919050565b6000815160201461312757600080fd5b506020015190565b600081600581111561314357613143614875565b0361315157610aa182612f9e565b600281600581111561316557613165614875565b0361020f57600061317583612f9e565b9050808360000181815161318991906141ae565b90525060208301515183511115610aa157600080fd5b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14613234576040516370a0823160e01b81526001600160a01b0384811660048301528316906370a0823190602401602060405180830381865afa15801561320b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061322f9190614465565b613240565b826001600160a01b0316315b9392505050565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156132a057507f000000000000000000000000000000000000000000000000000000000000000046145b156132ca57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156133a55750600090506003613429565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156133f9573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661342257600060019250925050613429565b9150600090505b94509492505050565b600081600481111561344657613446614875565b0361344e5750565b600181600481111561346257613462614875565b036134af5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016107a5565b60028160048111156134c3576134c3614875565b036135105760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016107a5565b600381600481111561352457613524614875565b036117145760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016107a5565b606061358b84846000856135f7565b949350505050565b60008082516041036135c95760208301516040840151606085015160001a6135bd8782858561336e565b945094505050506135d1565b506000905060025b9250929050565b600081516014146135e857600080fd5b5060200151600160601b900490565b6060824710156136585760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016107a5565b6001600160a01b0385163b6136af5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016107a5565b600080866001600160a01b031685876040516136cb919061488b565b60006040518083038185875af1925050503d8060008114613708576040519150601f19603f3d011682016040523d82523d6000602084013e61370d565b606091505b509150915061371d828286613728565b979650505050505050565b60608315613737575081613240565b8251156137475782518084602001fd5b8160405162461bcd60e51b81526004016107a591906148a7565b600060a0828403121561377357600080fd5b50919050565b600060c0828403121561377357600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156137c9576137c961378b565b604052919050565b60006001600160401b038211156137ea576137ea61378b565b5060051b60200190565b600082601f83011261380557600080fd5b81356001600160401b0381111561381e5761381e61378b565b613831601f8201601f19166020016137a1565b81815284602083860101111561384657600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261387457600080fd5b81356020613889613884836137d1565b6137a1565b82815260059290921b840181019181810190868411156138a857600080fd5b8286015b848110156138e75780356001600160401b038111156138cb5760008081fd5b6138d98986838b01016137f4565b8452509183019183016138ac565b509695505050505050565b6000806000610100848603121561390857600080fd5b83356001600160401b038082111561391f57600080fd5b61392b87838801613761565b945061393a8760208801613779565b935060e086013591508082111561395057600080fd5b5061395d86828701613863565b9150509250925092565b80356001600160a01b038116811461397e57600080fd5b919050565b6000602080838503121561399657600080fd5b82356001600160401b038111156139ac57600080fd5b8301601f810185136139bd57600080fd5b80356139cb613884826137d1565b81815260059190911b820183019083810190878311156139ea57600080fd5b928401925b8284101561371d57613a0084613967565b825292840192908401906139ef565b600060208284031215613a2157600080fd5b61324082613967565b600060208284031215613a3c57600080fd5b5035919050565b60008060e08385031215613a5657600080fd5b82356001600160401b03811115613a6c57600080fd5b613a7885828601613761565b925050613a888460208501613779565b90509250929050565b60008060408385031215613aa457600080fd5b613aad83613967565b946020939093013593505050565b60008083601f840112613acd57600080fd5b5081356001600160401b03811115613ae457600080fd5b6020830191508360208260051b85010111156135d157600080fd5b60008060008060008060006080888a031215613b1a57600080fd5b87356001600160401b0380821115613b3157600080fd5b613b3d8b838c016137f4565b985060208a0135915080821115613b5357600080fd5b613b5f8b838c01613abb565b909850965060408a0135915080821115613b7857600080fd5b613b848b838c01613abb565b909650945060608a0135915080821115613b9d57600080fd5b50613baa8a828b01613abb565b989b979a50959850939692959293505050565b6000806000806000806000806080898b031215613bd957600080fd5b88356001600160401b0380821115613bf057600080fd5b818b0191508b601f830112613c0457600080fd5b813581811115613c1357600080fd5b8c6020828501011115613c2557600080fd5b60209283019a509850908a01359080821115613c4057600080fd5b613c4c8c838d01613abb565b909850965060408b0135915080821115613c6557600080fd5b613c718c838d01613abb565b909650945060608b0135915080821115613c8a57600080fd5b50613c978b828c01613abb565b999c989b5096995094979396929594505050565b60008060208385031215613cbe57600080fd5b82356001600160401b0380821115613cd557600080fd5b818501915085601f830112613ce957600080fd5b813581811115613cf857600080fd5b8660208260061b8501011115613d0d57600080fd5b60209290920196919550909350505050565b60008060408385031215613d3257600080fd5b613d3b83613967565b9150613a8860208401613967565b600060208284031215613d5b57600080fd5b81356001600160401b03811115613d7157600080fd5b61358b84828501613761565b600060208284031215613d8f57600080fd5b81356001600160401b03811115613da557600080fd5b61358b848285016137f4565b60008060008060408587031215613dc757600080fd5b84356001600160401b0380821115613dde57600080fd5b613dea88838901613abb565b90965094506020870135915080821115613e0357600080fd5b50613e1087828801613abb565b95989497509550505050565b60005b83811015613e37578181015183820152602001613e1f565b50506000910152565b60008151808452613e58816020860160208601613e1c565b601f01601f19169290920160200192915050565b60c081526000613e7f60c0830189613e40565b6001600160a01b0397881660208401526001600160401b0396871660408401526060830195909552509190941660808201529290911660a090920191909152919050565b600060c08284031215613ed557600080fd5b6132408383613779565b600080600080600080600080600080600060c08c8e031215613f0057600080fd5b8b359a506001600160401b038060208e01351115613f1d57600080fd5b613f2d8e60208f01358f01613abb565b909b50995060408d0135811015613f4357600080fd5b613f538e60408f01358f01613abb565b909950975060608d0135811015613f6957600080fd5b613f798e60608f01358f01613abb565b909750955060808d0135811015613f8f57600080fd5b613f9f8e60808f01358f01613abb565b909550935060a08d0135811015613fb557600080fd5b50613fc68d60a08e01358e01613abb565b81935080925050509295989b509295989b9093969950565b600060c08284031215613ff057600080fd5b60405160c081018181106001600160401b03821117156140125761401261378b565b60405290508061402183613967565b815261402f60208401613967565b6020820152604083013560408201526060830135606082015261405460808401613967565b608082015260a083013560a08201525092915050565b60008060e0838503121561407d57600080fd5b6140878484613fde565b915060c08301356001600160401b038111156140a257600080fd5b6140ae85828601613863565b9150509250929050565b600080602083850312156140cb57600080fd5b82356001600160401b038111156140e157600080fd5b6140ed85828601613abb565b90969095509350505050565b80356001600160401b038116811461397e57600080fd5b6000806040838503121561412357600080fd5b61412c83613967565b9150613a88602084016140f9565b634e487b7160e01b600052601160045260246000fd5b8181038181111561150d5761150d61413a565b600060c0828403121561417557600080fd5b6132408383613fde565b634e487b7160e01b600052603260045260246000fd5b6000600182016141a7576141a761413a565b5060010190565b8082018082111561150d5761150d61413a565b60008160005b848110156141f6576001600160a01b036141e083613967565b16865260209586019591909101906001016141c7565b5093949350505050565b60006001600160fb1b0383111561421657600080fd5b8260051b80838637939093019392505050565b60006142406142398387896141c1565b8486614200565b9695505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8183526000602080850194508260005b858110156142af576001600160a01b0361429c83613967565b1687529582019590820190600101614283565b509495945050505050565b81835260006001600160fb1b038311156142d357600080fd5b8260051b80836020870137939093016020019392505050565b608081526000614300608083018a8c61424a565b602083820381850152818983528183019050818a60051b8401018b60005b8c81101561438d57858303601f190184528135368f9003601e1901811261434457600080fd5b8e0185810190356001600160401b0381111561435f57600080fd5b80360382131561436e57600080fd5b61437985828461424a565b95870195945050509084019060010161431e565b505085810360408701526143a2818a8c614273565b935050505082810360608401526143ba8185876142ba565b9b9a5050505050505050505050565b838152818360208301376000910160200190815292915050565b600181811c908216806143f757607f821691505b60208210810361377357634e487b7160e01b600052602260045260246000fd5b60006001600160401b038083168181036144335761443361413a565b6001019392505050565b86815285602082015260006144596142396040840187896141c1565b98975050505050505050565b60006020828403121561447757600080fd5b5051919050565b6000808335601e1984360301811261449557600080fd5b8301803591506001600160401b038211156144af57600080fd5b6020019150368190038213156135d157600080fd5b8183823760009101908152919050565b6000602082840312156144e657600080fd5b8151801515811461324057600080fd5b60006020828403121561450857600080fd5b613240826140f9565b6001600160601b0319606098891b8116825296881b871660148201529490961b9094166028840152603c8301919091526001600160c01b031960c091821b8116605c84015292811b831660648301529290921b16606c82015260740190565b60208082526034908201527f20504c455855533a207472616e73666572496420616c726561647920657869736040820152733a39971021b432b1b5903a3432903737b731b29760611b606082015260800190565b601f821115610aa157600081815260208120601f850160051c810160208610156145eb5750805b601f850160051c820191505b8181101561460a578281556001016145f7565b505050505050565b81516001600160401b0381111561462b5761462b61378b565b61463f8161463984546143e3565b846145c4565b602080601f831160018114614674576000841561465c5750858301515b600019600386901b1c1916600185901b17855561460a565b600085815260208120601f198616915b828110156146a357888601518255948401946001909101908401614684565b50858210156146c15787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0388811682526001600160401b0388811660208401529087166040830152606082018690528416608082015260a0810183905260e060c0820181905260009061472390830184613e40565b9998505050505050505050565b600060c0828403121561474257600080fd5b60405160c081018181106001600160401b03821117156147645761476461378b565b60405261477083613967565b81526020830135602082015261478860408401613967565b6040820152614799606084016140f9565b60608201526147aa608084016140f9565b608082015260a083013563ffffffff811681146147c657600080fd5b60a08201529392505050565b60208082526023908201527f7369676e65727320616e6420706f77657273206c656e677468206e6f74206d616040820152620e8c6d60eb1b606082015260800190565b808202811582820484141761150d5761150d61413a565b60008261484957634e487b7160e01b600052601260045260246000fd5b500490565b604081526000614862604083018688614273565b828103602084015261371d8185876142ba565b634e487b7160e01b600052602160045260246000fd5b6000825161489d818460208701613e1c565b9190910192915050565b6020815260006132406020830184613e4056fea26469706673582212204a52594efcf3bd898c8c89c045892005638648164495a82507b28ec38e2a44d564736f6c634300081100330000000000000000000000001111111254eeb25477b68fb85ed929f73a96058200000000000000000000000088dcdc47d2f83a99cf0000fdf667a468bb958a78
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001111111254eeb25477b68fb85ed929f73a96058200000000000000000000000088dcdc47d2f83a99cf0000fdf667a468bb958a78
-----Decoded View---------------
Arg [0] : router (address): 0x1111111254eeb25477b68fb85ed929f73a960582
Arg [1] : cbridge (address): 0x88dcdc47d2f83a99cf0000fdf667a468bb958a78
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000001111111254eeb25477b68fb85ed929f73a960582
Arg [1] : 00000000000000000000000088dcdc47d2f83a99cf0000fdf667a468bb958a78
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.