- Contract name:
- AnisticBridgeFactoryV2
- Optimization enabled
- true
- Compiler version
- v0.8.12+commit.f00d7308
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2022-05-30 07:48:11.690953Z
Contract source code
// SPDX-License-Identifier: MIT
// File: contracts/library/BridgeSecurity.sol
pragma solidity ^0.8.7;
library BridgeSecurity {
function generateSignerMsgHash(uint64 epoch, address[] memory signers)
internal
pure
returns (bytes32 msgHash)
{
msgHash = keccak256(
abi.encodePacked(
bytes1(0x19),
bytes1(0),
address(0),
epoch,
_encodeAddressArr(signers)
)
);
}
function generatePackMsgHash(
address thisAddr,
uint64 epoch,
uint8 networkId,
uint64[2] memory blockScanRange,
uint256[] memory txHashes,
address[] memory tokens,
address[] memory recipients,
uint256[] memory amounts
) internal pure returns (bytes32 msgHash) {
msgHash = keccak256(
abi.encodePacked(
bytes1(0x19),
bytes1(0),
thisAddr,
epoch,
_encodeFixed2Uint64Arr(blockScanRange),
networkId,
_encodeUint256Arr(txHashes),
_encodeAddressArr(tokens),
_encodeAddressArr(recipients),
_encodeUint256Arr(amounts)
)
);
}
function signersVerification(
bytes32 msgHash,
uint8[] memory v,
bytes32[] memory r,
bytes32[] memory s,
address[] memory signers,
mapping(address => bool) storage mapSigners
) internal view returns (bool) {
uint64 totalSigners = 0;
for (uint64 i = 0; i < signers.length; i++) {
if (mapSigners[signers[i]]) totalSigners++;
}
return (_getVerifiedSigners(msgHash, v, r, s, mapSigners) ==
(totalSigners / 2) + 1);
}
function _getVerifiedSigners(
bytes32 msgHash,
uint8[] memory v,
bytes32[] memory r,
bytes32[] memory s,
mapping(address => bool) storage mapSigners
) private view returns (uint8 verifiedSigners) {
address lastAddr = address(0);
verifiedSigners = 0;
for (uint64 i = 0; i < v.length; i++) {
address recovered = ecrecover(msgHash, v[i], r[i], s[i]);
if (recovered > lastAddr && mapSigners[recovered])
verifiedSigners++;
lastAddr = recovered;
}
}
function _encodeAddressArr(address[] memory arr)
private
pure
returns (bytes memory data)
{
for (uint64 i = 0; i < arr.length; i++) {
data = abi.encodePacked(data, arr[i]);
}
}
function _encodeUint256Arr(uint256[] memory arr)
private
pure
returns (bytes memory data)
{
for (uint64 i = 0; i < arr.length; i++) {
data = abi.encodePacked(data, arr[i]);
}
}
function _encodeFixed2Uint64Arr(uint64[2] memory arr)
private
pure
returns (bytes memory data)
{
for (uint64 i = 0; i < arr.length; i++) {
data = abi.encodePacked(data, arr[i]);
}
}
}
// File: contracts/BaseToken/interface/ITokenFactory.sol
pragma solidity ^0.8.7;
interface ITokenFactory {
event OwnerChanged(address indexed oldOwner, address indexed newOwner);
event BridgeChanged(address indexed oldBridge, address indexed newBridge);
event AdminChanged(address indexed oldAdmin, address indexed newAdmin);
event TokenCreated(
string name,
string indexed symbol,
uint256 amount,
uint8 decimal,
uint256 cap,
address indexed token
);
event TokenRemoved(address indexed token);
event TokenDecimalChanged(
address indexed token,
uint8 oldDecimal,
uint8 newDecimal
);
function owner() external view returns (address);
function tokens() external view returns (address[] memory);
function tokenExist(address token) external view returns (bool);
function bridge() external view returns (address);
function admin() external view returns (address);
function setBridge(address bridge) external;
function setAdmin(address admin) external;
function createToken(
string memory name,
string memory symbol,
uint256 amount,
uint8 decimal,
uint256 cap
) external returns (address token);
function removeToken(address token) external;
function setTokenDecimal(address token, uint8 decimal) external;
}
// File: contracts/BaseBridgeV2/interface/IBridgeV2.sol
pragma solidity ^0.8.7;
struct TokenReq {
bool exist;
uint256 minAmount;
uint256 maxAmount;
uint256 chargePercent;
uint256 minCharge;
uint256 maxCharge;
}
struct CrossTokenInfo {
string name;
string symbol;
}
struct NetworkInfo {
uint8 id;
string name;
}
struct TokenData {
address[] tokens;
address[] crossTokens;
uint256[] minAmounts;
uint256[] maxAmounts;
uint256[] chargePercents;
uint256[] minCharges;
uint256[] maxCharges;
uint8[] tokenTypes;
}
struct TokensInfo {
uint8[] ids;
address[][] tokens;
address[][] crossTokens;
uint256[][] minAmounts;
uint256[][] maxAmounts;
uint256[][] chargePercents;
uint256[][] minCharges;
uint256[][] maxCharges;
uint8[][] tokenTypes;
}
interface IBridgeV2 {
event TokenConnected(
address indexed token,
uint256 minAmount,
uint256 maxAmount,
uint256 percent,
uint256 minCharge,
uint256 maxCharge,
address indexed crossToken,
string symbol
);
event TokenReqChanged(
uint64 blockIndex,
address indexed token,
uint256[2] minAmount,
uint256[2] maxAmount,
uint256[2] percent,
uint256[2] minCharge,
uint256[2] maxCharge
);
function initialize(
address factory,
address admin,
address tokenFactory,
address wMech,
uint8 networkId,
string memory networkName
) external;
function factory() external view returns (address);
function admin() external view returns (address);
function network() external view returns (uint8, string memory);
function activeTokenCount() external view returns (uint8);
function crossToken(address crossToken)
external
view
returns (string memory, string memory);
function tokens(uint64 futureBlock, uint64 searchBlockIndex)
external
view
returns (TokenData memory data);
function blockScanRange() external view returns (uint64[] memory);
function txHash(uint256 txHash) external view returns (bool);
function setTokenConnection(
address token,
uint256 minAmount,
uint256 maxAmount,
uint256 percent,
uint256 minCharge,
uint256 maxCharge,
address crossToken,
string memory name,
string memory symbol
) external;
function setTokenInfo(
address token,
uint256 minAmount,
uint256 maxAmount,
uint256 percent,
uint256 minCharge,
uint256 maxCharge
) external;
function resetTokenConnection(address token, address crossToken) external;
function processPack(
uint64[2] memory blockScanRange,
uint256[] memory txHashes,
address[] memory tokens,
address[] memory recipients,
uint256[] memory amounts
) external;
function setScanRange(uint64[2] memory scanRange) external;
}
// File: contracts/library/BridgeUtilsV2.sol
pragma solidity ^0.8.7;
library BridgeUtilsV2 {
uint256 internal constant FUTURE_BLOCK_INTERVAL = 100;
uint256 public constant CHARGE_PERCENTAGE_DIVIDER = 10000;
function roundFuture(uint256 blockIndex) internal pure returns (uint64) {
uint256 _futureBlockIndex;
if (blockIndex <= FUTURE_BLOCK_INTERVAL) {
_futureBlockIndex = FUTURE_BLOCK_INTERVAL;
} else {
_futureBlockIndex =
FUTURE_BLOCK_INTERVAL *
((blockIndex / FUTURE_BLOCK_INTERVAL) + 1);
}
return uint64(_futureBlockIndex);
}
function getFuture(uint256 blockIndex)
internal
pure
returns (uint64 futureBlockIndex)
{
uint256 _futureBlockIndex;
if (blockIndex <= FUTURE_BLOCK_INTERVAL) {
_futureBlockIndex = 0;
} else {
_futureBlockIndex =
FUTURE_BLOCK_INTERVAL *
(blockIndex / FUTURE_BLOCK_INTERVAL);
}
return uint64(_futureBlockIndex);
}
function getBlockScanRange(
uint16 count,
uint8[] memory networks,
mapping(uint8 => address) storage bridges
)
internal
view
returns (uint8[] memory _networks, uint64[][] memory _ranges)
{
_networks = new uint8[](count);
_ranges = new uint64[][](count);
uint64 k = 0;
for (uint64 i = 0; i < networks.length; i++) {
if (bridges[networks[i]] != address(0)) {
_networks[k] = networks[i];
_ranges[k] = IBridgeV2(bridges[networks[i]]).blockScanRange();
k++;
}
}
}
function getTokenReq(
uint64 futureBlock,
address token,
uint64[] memory futureBlocks,
mapping(address => mapping(uint64 => TokenReq)) storage tokenReqs
)
internal
view
returns (
uint256 minAmount,
uint256 maxAmount,
uint256 percent,
uint256 minCharge,
uint256 maxCharge
)
{
TokenReq memory _req = getReq(
futureBlock,
token,
futureBlocks,
tokenReqs
);
minAmount = _req.minAmount;
maxAmount = _req.maxAmount;
percent = _req.chargePercent;
minCharge = _req.minCharge;
maxCharge = _req.maxCharge;
}
function updateMap(
address[] memory arr,
bool status,
mapping(address => bool) storage map
) internal {
for (uint64 i = 0; i < arr.length; i++) {
map[arr[i]] = status;
}
}
function getReq(
uint64 blockIndex,
address token,
uint64[] memory futureBlocks,
mapping(address => mapping(uint64 => TokenReq)) storage tokenReqs
) internal view returns (TokenReq memory req) {
req = tokenReqs[token][blockIndex];
if (!req.exist) {
for (uint256 i = futureBlocks.length; i > 0; i--) {
if (futureBlocks[i - 1] <= blockIndex) {
req = tokenReqs[token][futureBlocks[i - 1]];
if (req.exist) return req;
}
}
}
}
function getCountBySearchIndex(
uint64 searchBlockIndex,
address[] memory tokens,
mapping(address => bool) storage mapTokens,
mapping(address => uint64) storage mapTokenCreatedBlockIndex
) internal view returns (uint64 k) {
for (uint64 i = 0; i < tokens.length; i++) {
if (
mapTokens[tokens[i]] &&
(mapTokenCreatedBlockIndex[tokens[i]] <= searchBlockIndex)
) {
k++;
}
}
}
}
// File: contracts/BaseBridgeV2/interface/IBridgeStorageV2.sol
pragma solidity ^0.8.7;
interface IBridgeStorageV2 {
event OwnerChanged(address indexed oldOwner, address indexed newOwner);
event SignersChanged(
address[] indexed oldSigners,
address[] indexed newSigners
);
event RelayersChanged(
address[] indexed oldRelayers,
address[] indexed newRelayers
);
function activeNetworkCount() external view returns (uint16);
function owner() external view returns (address);
function admin() external view returns (address);
function factory() external view returns (address);
function epoch() external view returns (uint64);
function signers() external view returns (address[] memory);
function relayers() external view returns (address[] memory);
function ids() external view returns (uint8[] memory);
function mapSigner(address signer) external view returns (bool);
function mapRelayer(address relayer) external view returns (bool);
function bridge(uint8 id) external view returns (IBridgeV2);
function tokens(uint64 futureBlock, uint64 searchBlockIndex)
external
view
returns (TokensInfo memory info);
function setCallers(address admin, address factory) external;
function setEpoch(uint64 epoch) external;
function setSigners(address[] memory signers) external;
function setRelayers(address[] memory relayers) external;
function setBridge(uint8 networkId, address bridge) external;
function signerVerification(
bytes32 msgHash,
uint8[] memory v,
bytes32[] memory r,
bytes32[] memory s
) external view returns (bool);
}
// File: contracts/BaseToken/interface/IWrappedToken.sol
pragma solidity ^0.8.7;
interface IWrappedToken {
function deposit() external payable;
function withdraw(uint256 amount) external;
function withdrawTo(address recipient, uint256 amount) external;
}
// File: contracts/BaseBridgeV2/interface/IBridgeFactoryV2.sol
pragma solidity ^0.8.7;
interface IBridgeFactoryV2 {
event OwnerChanged(address indexed oldOwner, address indexed newOwner);
function owner() external view returns (address);
function epoch() external view returns (uint64);
function cap(address token) external view returns (uint256);
function tokens(uint64 searchBlockIndex)
external
view
returns (
uint8[] memory networkIds,
address[][] memory tokens,
address[][] memory crossTokens,
uint256[][] memory minAmounts,
uint256[][] memory maxAmounts,
uint256[][] memory chargePercents,
uint256[][] memory minCharges,
uint256[][] memory maxCharges,
uint8[][] memory tokenTypes
);
function blockScanRange(uint8 networkId)
external
view
returns (uint64[] memory blockScanRange);
function processSigners(
uint64 epoch,
address[] memory signers,
uint8[] memory v,
bytes32[] memory r,
bytes32[] memory s
) external;
function processPack(
uint8 networkId,
uint64[2] memory scanRange,
uint256[] memory txHashes,
address[] memory tokens,
address[] memory recipients,
uint256[] memory amounts,
uint8[] memory v,
bytes32[] memory r,
bytes32[] memory s
) external;
function setSigners(address[] memory signers) external;
function setRelayers(address[] memory relayers) external;
function transfer(
uint8 id,
address token,
address recipient,
uint256 amount
) external;
function withdrawTo(
uint8 id,
IWrappedToken wt,
address recipient,
uint256 amount
) external;
function mint(
uint8 id,
address token,
address recipient,
uint256 amount
) external;
function withdrawal(
address token,
address recipient,
uint256 amount,
uint8[] memory v,
bytes32[] memory r,
bytes32[] memory s
) external;
}
// File: @openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
// OpenZeppelin Contracts v4.4.0 (utils/Address.sol)
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(
address(this).balance >= amount,
"Address: insufficient balance"
);
(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 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);
}
}
}
}
// File: @openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol
// OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount)
external
returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender)
external
view
returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
// File: contracts/BaseToken/interface/ITokenMintable.sol
pragma solidity ^0.8.7;
interface ITokenMintable is IERC20Upgradeable {
function initialize(
address factory,
string memory name,
string memory symbol,
uint256 amount,
uint8 decimal,
uint256 cap
) external;
function factory() external view returns (address);
function decimals() external view returns (uint8);
function cap() external view returns (uint256);
function mint(address to, uint256 amount) external;
function burn(uint256 amount) external;
function increaseCap(uint256 cap) external;
function setupDecimal(uint8 decimal) external;
}
// File: @openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol
// OpenZeppelin Contracts v4.4.0 (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
/**
* @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 SafeERC20Upgradeable {
using AddressUpgradeable for address;
function safeTransfer(
IERC20Upgradeable token,
address to,
uint256 value
) internal {
_callOptionalReturn(
token,
abi.encodeWithSelector(token.transfer.selector, to, value)
);
}
function safeTransferFrom(
IERC20Upgradeable 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(
IERC20Upgradeable 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(
IERC20Upgradeable 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(
IERC20Upgradeable 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(IERC20Upgradeable 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"
);
}
}
}
// File: @openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// OpenZeppelin Contracts v4.4.0 (proxy/utils/Initializable.sol)
pragma solidity ^0.8.0;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
* initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() initializer {}
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(
_initializing || !_initialized,
"Initializable: contract is already initialized"
);
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
}
// File: @openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// OpenZeppelin Contracts v4.4.0 (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 ContextUpgradeable is Initializable {
function __Context_init() internal initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
uint256[50] private __gap;
}
// File: @openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol
// OpenZeppelin Contracts v4.4.0 (access/Ownable.sol)
pragma solidity ^0.8.0;
/**
* @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 OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal initializer {
__Context_init_unchained();
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal initializer {
_transferOwnership(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_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);
}
uint256[49] private __gap;
}
// File: contracts/BaseBridgeV2/base/BridgeFactoryUpgradeableV2.sol
pragma solidity ^0.8.7;
contract BridgeFactoryUpgradeableV2 is
Initializable,
OwnableUpgradeable,
IBridgeFactoryV2
{
using SafeERC20Upgradeable for ITokenMintable;
using BridgeSecurity for *;
using BridgeUtilsV2 for *;
IBridgeStorageV2 private bs;
address[] private _wdSigners;
mapping(address => bool) private _mapWdSigners;
modifier onlyChild(uint8 id) {
require(bs.bridge(id) == IBridgeV2(msg.sender), "OB");
_;
}
modifier onlyRelayer() {
require(bs.mapRelayer(msg.sender), "OR");
_;
}
function __BridgeFactory_init(
address bridgeStorage,
address[] memory wdSigners_
) internal initializer {
__Ownable_init();
bs = IBridgeStorageV2(bridgeStorage);
_wdSigners = wdSigners_;
for (uint64 i = 0; i < wdSigners_.length; i++) {
_mapWdSigners[wdSigners_[i]] = true;
}
}
function owner()
public
view
override(OwnableUpgradeable, IBridgeFactoryV2)
returns (address)
{
return OwnableUpgradeable.owner();
}
function epoch() public view override returns (uint64 epoch_) {
epoch_ = bs.epoch();
}
function cap(address token) external view override returns (uint256 _cap) {
return ITokenMintable(token).cap();
}
function wdSigners() external view returns (address[] memory) {
return _wdSigners;
}
function tokens(uint64 searchBlockIndex)
external
view
override
returns (
uint8[] memory networkIds,
address[][] memory tokens_,
address[][] memory crossTokens,
uint256[][] memory minAmounts,
uint256[][] memory maxAmounts,
uint256[][] memory chargePercents,
uint256[][] memory minCharges,
uint256[][] memory maxCharges,
uint8[][] memory tokenTypes
)
{
uint64 futureBlock = searchBlockIndex.getFuture();
TokensInfo memory info = bs.tokens(futureBlock, searchBlockIndex);
return (
info.ids,
info.tokens,
info.crossTokens,
info.minAmounts,
info.maxAmounts,
info.chargePercents,
info.minCharges,
info.maxCharges,
info.tokenTypes
);
}
function blockScanRange(uint8 networkId)
external
view
override
returns (uint64[] memory blockScanRange_)
{
if (bs.bridge(networkId) != IBridgeV2(address(0)))
blockScanRange_ = bs.bridge(networkId).blockScanRange();
}
function processSigners(
uint64 epoch_,
address[] memory signers_,
uint8[] memory v,
bytes32[] memory r,
bytes32[] memory s
) external override onlyRelayer {
require(epoch_ > epoch(), "IE");
bytes32 msgHash = epoch_.generateSignerMsgHash(signers_);
if (bs.signerVerification(msgHash, v, r, s)) {
bs.setEpoch(epoch_);
bs.setSigners(signers_);
}
}
function processPack(
uint8 networkId,
uint64[2] memory blockScanRange_,
uint256[] memory txHashes,
address[] memory tokens_,
address[] memory recipients,
uint256[] memory amounts,
uint8[] memory v,
bytes32[] memory r,
bytes32[] memory s
) external override onlyRelayer {
require(bs.bridge(networkId) != IBridgeV2(address(0)), "NXE");
require(blockScanRange_[1] > blockScanRange_[0], "IR");
bytes32 msgHash = address(this).generatePackMsgHash(
epoch(),
networkId,
blockScanRange_,
txHashes,
tokens_,
recipients,
amounts
);
if (bs.signerVerification(msgHash, v, r, s)) {
bs.bridge(networkId).processPack(
blockScanRange_,
txHashes,
tokens_,
recipients,
amounts
);
}
}
function setSigners(address[] memory signers)
external
virtual
override
onlyOwner
{
bs.setSigners(signers);
}
function setRelayers(address[] memory relayers)
external
virtual
override
onlyOwner
{
bs.setRelayers(relayers);
}
function transfer(
uint8 id,
address token,
address recipient,
uint256 amount
) external virtual override onlyChild(id) {
ITokenMintable(token).safeTransfer(recipient, amount);
}
function withdrawTo(
uint8 id,
IWrappedToken wt,
address recipient,
uint256 amount
) external virtual override onlyChild(id) {
wt.withdrawTo(recipient, amount);
}
function mint(
uint8 id,
address token,
address recipient,
uint256 amount
) external virtual override onlyChild(id) {
ITokenMintable(token).mint(recipient, amount);
}
function withdrawal(
address token,
address recipient,
uint256 amount,
uint8[] memory v,
bytes32[] memory r,
bytes32[] memory s
) external virtual override onlyOwner {
require(token != address(0), "ZA");
require(recipient != address(0), "ZA");
require(r.length == _wdSigners.length, "SG1");
bytes32 msgHash = keccak256(
abi.encodePacked(
bytes1(0x19),
bytes1(0),
address(this),
token,
recipient,
amount
)
);
bytes memory prefix = "\x19Ethereum Signed Message:\n32";
msgHash = keccak256(abi.encodePacked(prefix, msgHash));
uint64 verified = 0;
address lastAddr = address(0);
for (uint64 i = 0; i < _wdSigners.length; i++) {
address recovered = ecrecover(msgHash, v[i], r[i], s[i]);
require(recovered > lastAddr && _mapWdSigners[recovered], "SG2");
lastAddr = recovered;
verified++;
}
if (verified == _wdSigners.length) {
ITokenMintable(token).safeTransfer(recipient, amount);
}
}
}
// File: contracts/Net-Anistic/BridgeV2/AnisticBridgeFactoryV2.sol
pragma solidity ^0.8.7;
contract AnisticBridgeFactoryV2 is BridgeFactoryUpgradeableV2 {
event Transfer(address indexed src, address indexed dst, uint256 wad);
IWrappedToken wmech;
function initialize(
address bridgeStorage,
address wmech_,
address[] memory wdSigners
) public initializer {
wmech = IWrappedToken(wmech_);
__BridgeFactory_init(bridgeStorage, wdSigners);
}
fallback() external payable {
wmech.deposit{value: msg.value}();
emit Transfer(msg.sender, address(this), msg.value);
}
receive() external payable {}
}
Contract ABI
[{"type":"event","name":"OwnerChanged","inputs":[{"type":"address","name":"oldOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"src","internalType":"address","indexed":true},{"type":"address","name":"dst","internalType":"address","indexed":true},{"type":"uint256","name":"wad","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"fallback","stateMutability":"payable"},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64[]","name":"blockScanRange_","internalType":"uint64[]"}],"name":"blockScanRange","inputs":[{"type":"uint8","name":"networkId","internalType":"uint8"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_cap","internalType":"uint256"}],"name":"cap","inputs":[{"type":"address","name":"token","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"epoch_","internalType":"uint64"}],"name":"epoch","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"bridgeStorage","internalType":"address"},{"type":"address","name":"wmech_","internalType":"address"},{"type":"address[]","name":"wdSigners","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"mint","inputs":[{"type":"uint8","name":"id","internalType":"uint8"},{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"processPack","inputs":[{"type":"uint8","name":"networkId","internalType":"uint8"},{"type":"uint64[2]","name":"blockScanRange_","internalType":"uint64[2]"},{"type":"uint256[]","name":"txHashes","internalType":"uint256[]"},{"type":"address[]","name":"tokens_","internalType":"address[]"},{"type":"address[]","name":"recipients","internalType":"address[]"},{"type":"uint256[]","name":"amounts","internalType":"uint256[]"},{"type":"uint8[]","name":"v","internalType":"uint8[]"},{"type":"bytes32[]","name":"r","internalType":"bytes32[]"},{"type":"bytes32[]","name":"s","internalType":"bytes32[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"processSigners","inputs":[{"type":"uint64","name":"epoch_","internalType":"uint64"},{"type":"address[]","name":"signers_","internalType":"address[]"},{"type":"uint8[]","name":"v","internalType":"uint8[]"},{"type":"bytes32[]","name":"r","internalType":"bytes32[]"},{"type":"bytes32[]","name":"s","internalType":"bytes32[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRelayers","inputs":[{"type":"address[]","name":"relayers","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setSigners","inputs":[{"type":"address[]","name":"signers","internalType":"address[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8[]","name":"networkIds","internalType":"uint8[]"},{"type":"address[][]","name":"tokens_","internalType":"address[][]"},{"type":"address[][]","name":"crossTokens","internalType":"address[][]"},{"type":"uint256[][]","name":"minAmounts","internalType":"uint256[][]"},{"type":"uint256[][]","name":"maxAmounts","internalType":"uint256[][]"},{"type":"uint256[][]","name":"chargePercents","internalType":"uint256[][]"},{"type":"uint256[][]","name":"minCharges","internalType":"uint256[][]"},{"type":"uint256[][]","name":"maxCharges","internalType":"uint256[][]"},{"type":"uint8[][]","name":"tokenTypes","internalType":"uint8[][]"}],"name":"tokens","inputs":[{"type":"uint64","name":"searchBlockIndex","internalType":"uint64"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transfer","inputs":[{"type":"uint8","name":"id","internalType":"uint8"},{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"wdSigners","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawTo","inputs":[{"type":"uint8","name":"id","internalType":"uint8"},{"type":"address","name":"wt","internalType":"contract IWrappedToken"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawal","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint8[]","name":"v","internalType":"uint8[]"},{"type":"bytes32[]","name":"r","internalType":"bytes32[]"},{"type":"bytes32[]","name":"s","internalType":"bytes32[]"}]},{"type":"receive","stateMutability":"payable"}]
Deployed ByteCode
0x6080604052600436106101025760003560e01c80638da5cb5b11610095578063a377266211610064578063a377266214610347578063a6bf32d114610367578063a8f3fdb814610395578063baa51b56146103ca578063f2fde38b146103f757610109565b80638da5cb5b146102ad578063900cf0cf146102da578063984821fe146103075780639f7ca4be1461032757610109565b80633e5db744116100d15780633e5db744146102385780634fae650114610258578063715018a61461027857806377a24f361461028d57610109565b8063012e98d1146101ab5780630331f2b7146101cd578063090a6d09146101ed57806332a2fd8c1461021857610109565b3661010957005b606860009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561015957600080fd5b505af115801561016d573d6000803e3d6000fd5b50506040513481523093503392507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef915060200160405180910390a3005b3480156101b757600080fd5b506101cb6101c6366004611d7b565b610417565b005b3480156101d957600080fd5b506101cb6101e8366004611d7b565b610523565b3480156101f957600080fd5b506102026105f1565b60405161020f9190611e10565b60405180910390f35b34801561022457600080fd5b506101cb610233366004611f84565b610653565b34801561024457600080fd5b506101cb61025336600461212a565b610999565b34801561026457600080fd5b506101cb610273366004612268565b610ca0565b34801561028457600080fd5b506101cb610ee8565b34801561029957600080fd5b506101cb6102a8366004612327565b610f23565b3480156102b957600080fd5b506102c2610fb7565b6040516001600160a01b03909116815260200161020f565b3480156102e657600080fd5b506102ef610fd0565b6040516001600160401b03909116815260200161020f565b34801561031357600080fd5b506101cb610322366004612388565b61103e565b34801561033357600080fd5b506101cb610342366004611d7b565b6110d2565b34801561035357600080fd5b506101cb610362366004612388565b61117f565b34801561037357600080fd5b506103876103823660046123bc565b6111de565b60405190815260200161020f565b3480156103a157600080fd5b506103b56103b03660046123d9565b611248565b60405161020f99989796959493929190612536565b3480156103d657600080fd5b506103ea6103e5366004612641565b611342565b60405161020f919061265e565b34801561040357600080fd5b506101cb6104123660046123bc565b61149e565b60655460405163d80b21d760e01b815260ff86166004820152859133916001600160a01b039091169063d80b21d790602401602060405180830381865afa158015610466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048a91906126ab565b6001600160a01b0316146104b95760405162461bcd60e51b81526004016104b0906126c8565b60405180910390fd5b60405163040b850f60e31b81526001600160a01b0384811660048301526024820184905285169063205c2878906044015b600060405180830381600087803b15801561050457600080fd5b505af1158015610518573d6000803e3d6000fd5b505050505050505050565b60655460405163d80b21d760e01b815260ff86166004820152859133916001600160a01b039091169063d80b21d790602401602060405180830381865afa158015610572573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059691906126ab565b6001600160a01b0316146105bc5760405162461bcd60e51b81526004016104b0906126c8565b6040516340c10f1960e01b81526001600160a01b038481166004830152602482018490528516906340c10f19906044016104ea565b6060606680548060200260200160405190810160405280929190818152602001828054801561064957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161062b575b5050505050905090565b3361065c610fb7565b6001600160a01b0316146106825760405162461bcd60e51b81526004016104b0906126e4565b6001600160a01b0386166106bd5760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016104b0565b6001600160a01b0385166106f85760405162461bcd60e51b81526020600482015260026024820152615a4160f01b60448201526064016104b0565b6066548251146107305760405162461bcd60e51b815260206004820152600360248201526253473160e81b60448201526064016104b0565b604051601960f81b60208201526000602182018190526001600160601b031930606090811b8216602285015289811b8216603685015288901b16604a830152605e820186905290607e0160408051601f1981840301815282825280516020918201208383018352601c84527f19457468657265756d205369676e6564204d6573736167653a0a3332000000008483015291519193506107d3918391859101612761565b60405160208183030381529060405280519060200120915060008060005b6066546001600160401b03821610156109655760006001868a846001600160401b03168151811061082457610824612783565b60200260200101518a856001600160401b03168151811061084757610847612783565b60200260200101518a866001600160401b03168151811061086a5761086a612783565b6020026020010151604051600081526020016040526040516108a8949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156108ca573d6000803e3d6000fd5b505050602060405103519050826001600160a01b0316816001600160a01b031611801561090f57506001600160a01b03811660009081526067602052604090205460ff165b6109415760405162461bcd60e51b815260206004820152600360248201526229a39960e91b60448201526064016104b0565b9150818361094e816127af565b94505050808061095d906127af565b9150506107f1565b506066546001600160401b038316141561098d5761098d6001600160a01b038b168a8a61153e565b50505050505050505050565b60655460405163f0d899e160e01b81523360048201526001600160a01b039091169063f0d899e190602401602060405180830381865afa1580156109e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0591906127d6565b610a365760405162461bcd60e51b815260206004820152600260248201526127a960f11b60448201526064016104b0565b60655460405163d80b21d760e01b815260ff8b1660048201526000916001600160a01b03169063d80b21d790602401602060405180830381865afa158015610a82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa691906126ab565b6001600160a01b03161415610ae35760405162461bcd60e51b81526020600482015260036024820152624e584560e81b60448201526064016104b0565b875160208901516001600160401b03918216911611610b295760405162461bcd60e51b815260206004820152600260248201526124a960f11b60448201526064016104b0565b6000610b43610b36610fd0565b30908c8c8c8c8c8c611595565b60655460405163759886dd60e01b81529192506001600160a01b03169063759886dd90610b7a9084908890889088906004016127f8565b602060405180830381865afa158015610b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bbb91906127d6565b1561098d5760655460405163d80b21d760e01b815260ff8c1660048201526001600160a01b039091169063d80b21d790602401602060405180830381865afa158015610c0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2f91906126ab565b6001600160a01b03166337d494298a8a8a8a8a6040518663ffffffff1660e01b8152600401610c62959493929190612837565b600060405180830381600087803b158015610c7c57600080fd5b505af1158015610c90573d6000803e3d6000fd5b5050505050505050505050505050565b60655460405163f0d899e160e01b81523360048201526001600160a01b039091169063f0d899e190602401602060405180830381865afa158015610ce8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0c91906127d6565b610d3d5760405162461bcd60e51b815260206004820152600260248201526127a960f11b60448201526064016104b0565b610d45610fd0565b6001600160401b0316856001600160401b031611610d8a5760405162461bcd60e51b8152602060048201526002602482015261494560f01b60448201526064016104b0565b6000610d9f6001600160401b0387168661160a565b60655460405163759886dd60e01b81529192506001600160a01b03169063759886dd90610dd69084908890889088906004016127f8565b602060405180830381865afa158015610df3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1791906127d6565b15610ee0576065546040516311bde4fb60e01b81526001600160401b03881660048201526001600160a01b03909116906311bde4fb90602401600060405180830381600087803b158015610e6a57600080fd5b505af1158015610e7e573d6000803e3d6000fd5b50506065546040516351bb933160e11b81526001600160a01b03909116925063a37726629150610eb2908890600401611e10565b600060405180830381600087803b158015610ecc57600080fd5b505af115801561098d573d6000803e3d6000fd5b505050505050565b33610ef1610fb7565b6001600160a01b031614610f175760405162461bcd60e51b81526004016104b0906126e4565b610f21600061164f565b565b600054610100900460ff1680610f3c575060005460ff16155b610f585760405162461bcd60e51b81526004016104b0906128c2565b600054610100900460ff16158015610f7a576000805461ffff19166101011790555b606880546001600160a01b0319166001600160a01b038516179055610f9f84836116a1565b8015610fb1576000805461ff00191690555b50505050565b6000610fcb6033546001600160a01b031690565b905090565b6065546040805163900cf0cf60e01b815290516000926001600160a01b03169163900cf0cf9160048083019260209291908290030181865afa15801561101a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcb9190612910565b33611047610fb7565b6001600160a01b03161461106d5760405162461bcd60e51b81526004016104b0906126e4565b606554604051634c2410ff60e11b81526001600160a01b039091169063984821fe9061109d908490600401611e10565b600060405180830381600087803b1580156110b757600080fd5b505af11580156110cb573d6000803e3d6000fd5b5050505050565b60655460405163d80b21d760e01b815260ff86166004820152859133916001600160a01b039091169063d80b21d790602401602060405180830381865afa158015611121573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114591906126ab565b6001600160a01b03161461116b5760405162461bcd60e51b81526004016104b0906126c8565b6110cb6001600160a01b038516848461153e565b33611188610fb7565b6001600160a01b0316146111ae5760405162461bcd60e51b81526004016104b0906126e4565b6065546040516351bb933160e11b81526001600160a01b039091169063a37726629061109d908490600401611e10565b6000816001600160a01b031663355274ea6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561121e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611242919061292d565b92915050565b6060806060806060806060806060600061126a8b6001600160401b03166117c0565b606554604051636dadfa4760e01b81526001600160401b0380841660048301528e1660248201529192506000916001600160a01b0390911690636dadfa4790604401600060405180830381865afa1580156112c9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112f19190810190612be8565b9050806000015181602001518260400151836060015184608001518560a001518660c001518760e001518861010001519a509a509a509a509a509a509a509a509a5050509193959799909294969850565b60655460405163d80b21d760e01b815260ff831660048201526060916000916001600160a01b039091169063d80b21d790602401602060405180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b791906126ab565b6001600160a01b0316146114995760655460405163d80b21d760e01b815260ff841660048201526001600160a01b039091169063d80b21d790602401602060405180830381865afa158015611410573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143491906126ab565b6001600160a01b0316633f47c9ae6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611471573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112429190810190612d79565b919050565b336114a7610fb7565b6001600160a01b0316146114cd5760405162461bcd60e51b81526004016104b0906126e4565b6001600160a01b0381166115325760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016104b0565b61153b8161164f565b50565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526115909084906117f0565b505050565b6000601960f81b818a8a6115a88a6118c2565b8b6115b28b611935565b6115bb8b6119a5565b6115c48b6119a5565b6115cd8b611935565b6040516020016115e69a99989796959493929190612e07565b60405160208183030381529060405280519060200120905098975050505050505050565b6000601960f81b81808561161d866119a5565b604051602001611631959493929190612ec1565b60405160208183030381529060405280519060200120905092915050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16806116ba575060005460ff16155b6116d65760405162461bcd60e51b81526004016104b0906128c2565b600054610100900460ff161580156116f8576000805461ffff19166101011790555b611700611a15565b606580546001600160a01b0319166001600160a01b038516179055815161172e906066906020850190611cd2565b5060005b8251816001600160401b031610156117a95760016067600085846001600160401b03168151811061176557611765612783565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff1916911515919091179055806117a1816127af565b915050611732565b508015611590576000805461ff0019169055505050565b600080606483116117d357506000611242565b6117de606484612f25565b6117e9906064612f47565b9392505050565b6000611845826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611a909092919063ffffffff16565b805190915015611590578080602001905181019061186391906127d6565b6115905760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016104b0565b606060005b6002816001600160401b0316101561192f578183826001600160401b0316600281106118f5576118f5612783565b602002015160405160200161190b929190612f66565b60405160208183030381529060405291508080611927906127af565b9150506118c7565b50919050565b606060005b8251816001600160401b0316101561192f578183826001600160401b03168151811061196857611968612783565b6020026020010151604051602001611981929190612761565b6040516020818303038152906040529150808061199d906127af565b91505061193a565b606060005b8251816001600160401b0316101561192f578183826001600160401b0316815181106119d8576119d8612783565b60200260200101516040516020016119f1929190612f98565b60405160208183030381529060405291508080611a0d906127af565b9150506119aa565b600054610100900460ff1680611a2e575060005460ff16155b611a4a5760405162461bcd60e51b81526004016104b0906128c2565b600054610100900460ff16158015611a6c576000805461ffff19166101011790555b611a74611aa7565b611a7c611b11565b801561153b576000805461ff001916905550565b6060611a9f8484600085611b71565b949350505050565b600054610100900460ff1680611ac0575060005460ff16155b611adc5760405162461bcd60e51b81526004016104b0906128c2565b600054610100900460ff16158015611a7c576000805461ffff1916610101179055801561153b576000805461ff001916905550565b600054610100900460ff1680611b2a575060005460ff16155b611b465760405162461bcd60e51b81526004016104b0906128c2565b600054610100900460ff16158015611b68576000805461ffff19166101011790555b611a7c3361164f565b606082471015611bd25760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016104b0565b843b611c205760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104b0565b600080866001600160a01b03168587604051611c3c9190612fca565b60006040518083038185875af1925050503d8060008114611c79576040519150601f19603f3d011682016040523d82523d6000602084013e611c7e565b606091505b5091509150611c8e828286611c99565b979650505050505050565b60608315611ca85750816117e9565b825115611cb85782518084602001fd5b8160405162461bcd60e51b81526004016104b09190612fe6565b828054828255906000526020600020908101928215611d27579160200282015b82811115611d2757825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190611cf2565b50611d33929150611d37565b5090565b5b80821115611d335760008155600101611d38565b60ff8116811461153b57600080fd5b803561149981611d4c565b6001600160a01b038116811461153b57600080fd5b60008060008060808587031215611d9157600080fd5b8435611d9c81611d4c565b93506020850135611dac81611d66565b92506040850135611dbc81611d66565b9396929550929360600135925050565b600081518084526020808501945080840160005b83811015611e055781516001600160a01b031687529582019590820190600101611de0565b509495945050505050565b6020815260006117e96020830184611dcc565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b0381118282101715611e5c57611e5c611e23565b60405290565b604051601f8201601f191681016001600160401b0381118282101715611e8a57611e8a611e23565b604052919050565b60006001600160401b03821115611eab57611eab611e23565b5060051b60200190565b600082601f830112611ec657600080fd5b81356020611edb611ed683611e92565b611e62565b82815260059290921b84018101918181019086841115611efa57600080fd5b8286015b84811015611f1e578035611f1181611d4c565b8352918301918301611efe565b509695505050505050565b600082601f830112611f3a57600080fd5b81356020611f4a611ed683611e92565b82815260059290921b84018101918181019086841115611f6957600080fd5b8286015b84811015611f1e5780358352918301918301611f6d565b60008060008060008060c08789031215611f9d57600080fd5b8635611fa881611d66565b95506020870135611fb881611d66565b94506040870135935060608701356001600160401b0380821115611fdb57600080fd5b611fe78a838b01611eb5565b94506080890135915080821115611ffd57600080fd5b6120098a838b01611f29565b935060a089013591508082111561201f57600080fd5b5061202c89828a01611f29565b9150509295509295509295565b6001600160401b038116811461153b57600080fd5b600082601f83011261205f57600080fd5b604051604081018181106001600160401b038211171561208157612081611e23565b806040525080604084018581111561209857600080fd5b845b818110156120bb5780356120ad81612039565b83526020928301920161209a565b509195945050505050565b600082601f8301126120d757600080fd5b813560206120e7611ed683611e92565b82815260059290921b8401810191818101908684111561210657600080fd5b8286015b84811015611f1e57803561211d81611d66565b835291830191830161210a565b60008060008060008060008060006101408a8c03121561214957600080fd5b6121528a611d5b565b98506121618b60208c0161204e565b975060608a01356001600160401b038082111561217d57600080fd5b6121898d838e01611f29565b985060808c013591508082111561219f57600080fd5b6121ab8d838e016120c6565b975060a08c01359150808211156121c157600080fd5b6121cd8d838e016120c6565b965060c08c01359150808211156121e357600080fd5b6121ef8d838e01611f29565b955060e08c013591508082111561220557600080fd5b6122118d838e01611eb5565b94506101008c013591508082111561222857600080fd5b6122348d838e01611f29565b93506101208c013591508082111561224b57600080fd5b506122588c828d01611f29565b9150509295985092959850929598565b600080600080600060a0868803121561228057600080fd5b853561228b81612039565b945060208601356001600160401b03808211156122a757600080fd5b6122b389838a016120c6565b955060408801359150808211156122c957600080fd5b6122d589838a01611eb5565b945060608801359150808211156122eb57600080fd5b6122f789838a01611f29565b9350608088013591508082111561230d57600080fd5b5061231a88828901611f29565b9150509295509295909350565b60008060006060848603121561233c57600080fd5b833561234781611d66565b9250602084013561235781611d66565b915060408401356001600160401b0381111561237257600080fd5b61237e868287016120c6565b9150509250925092565b60006020828403121561239a57600080fd5b81356001600160401b038111156123b057600080fd5b611a9f848285016120c6565b6000602082840312156123ce57600080fd5b81356117e981611d66565b6000602082840312156123eb57600080fd5b81356117e981612039565b600081518084526020808501945080840160005b83811015611e0557815160ff168752958201959082019060010161240a565b600082825180855260208086019550808260051b8401018186016000805b858110156124a357868403601f19018a52825180518086529086019086860190845b8181101561248e5783516001600160a01b031683529288019291880191600101612469565b50509a86019a94505091840191600101612447565b509198975050505050505050565b600081518084526020808501945080840160005b83811015611e05578151875295820195908201906001016124c5565b600081518084526020808501808196508360051b8101915082860160005b858110156125295782840389526125178483516124b1565b988501989350908401906001016124ff565b5091979650505050505050565b600061012080835261254a8184018d6123f6565b905060208382038185015261255f828d612429565b91508382036040850152612573828c612429565b91508382036060850152612587828b6124e1565b9150838203608085015261259b828a6124e1565b915083820360a08501526125af82896124e1565b915083820360c08501526125c382886124e1565b915083820360e08501526125d782876124e1565b91508382036101008501528185518084528284019150828160051b85010183880160005b8381101561262957601f198784030185526126178383516123f6565b948601949250908501906001016125fb565b505080955050505050509a9950505050505050505050565b60006020828403121561265357600080fd5b81356117e981611d4c565b6020808252825182820181905260009190848201906040850190845b8181101561269f5783516001600160401b03168352928401929184019160010161267a565b50909695505050505050565b6000602082840312156126bd57600080fd5b81516117e981611d66565b60208082526002908201526127a160f11b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60005b8381101561273457818101518382015260200161271c565b83811115610fb15750506000910152565b60008151612757818560208601612719565b9290920192915050565b60008351612773818460208801612719565b9190910191825250602001919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001600160401b03808316818114156127cc576127cc612799565b6001019392505050565b6000602082840312156127e857600080fd5b815180151581146117e957600080fd5b84815260806020820152600061281160808301866123f6565b828103604084015261282381866124b1565b90508281036060840152611c8e81856124b1565b60008187825b60028110156128655781516001600160401b031683526020928301929091019060010161283d565b50505060c0604083015261287c60c08301876124b1565b828103606084015261288e8187611dcc565b905082810360808401526128a28186611dcc565b905082810360a08401526128b681856124b1565b98975050505050505050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60006020828403121561292257600080fd5b81516117e981612039565b60006020828403121561293f57600080fd5b5051919050565b600082601f83011261295757600080fd5b81516020612967611ed683611e92565b82815260059290921b8401810191818101908684111561298657600080fd5b8286015b84811015611f1e57805161299d81611d4c565b835291830191830161298a565b600082601f8301126129bb57600080fd5b815160206129cb611ed683611e92565b828152600592831b85018201928282019190878511156129ea57600080fd5b8387015b85811015612a895780516001600160401b03811115612a0d5760008081fd5b8801603f81018a13612a1f5760008081fd5b858101516040612a31611ed683611e92565b82815291851b8301810191888101908d841115612a4e5760008081fd5b938201935b83851015612a785784519250612a6883611d66565b8282529389019390890190612a53565b8852505050938501935084016129ee565b5090979650505050505050565b600082601f830112612aa757600080fd5b81516020612ab7611ed683611e92565b828152600592831b8501820192828201919087851115612ad657600080fd5b8387015b85811015612a895780516001600160401b03811115612af95760008081fd5b8801603f81018a13612b0b5760008081fd5b858101516040612b1d611ed683611e92565b82815291851b8301810191888101908d841115612b3a5760008081fd5b938201935b83851015612b5857845182529389019390890190612b3f565b885250505093850193508401612ada565b600082601f830112612b7a57600080fd5b81516020612b8a611ed683611e92565b82815260059290921b84018101918181019086841115612ba957600080fd5b8286015b84811015611f1e5780516001600160401b03811115612bcc5760008081fd5b612bda8986838b0101612946565b845250918301918301612bad565b600060208284031215612bfa57600080fd5b81516001600160401b0380821115612c1157600080fd5b908301906101208286031215612c2657600080fd5b612c2e611e39565b825182811115612c3d57600080fd5b612c4987828601612946565b825250602083015182811115612c5e57600080fd5b612c6a878286016129aa565b602083015250604083015182811115612c8257600080fd5b612c8e878286016129aa565b604083015250606083015182811115612ca657600080fd5b612cb287828601612a96565b606083015250608083015182811115612cca57600080fd5b612cd687828601612a96565b60808301525060a083015182811115612cee57600080fd5b612cfa87828601612a96565b60a08301525060c083015182811115612d1257600080fd5b612d1e87828601612a96565b60c08301525060e083015182811115612d3657600080fd5b612d4287828601612a96565b60e0830152506101008084015183811115612d5c57600080fd5b612d6888828701612b69565b918301919091525095945050505050565b60006020808385031215612d8c57600080fd5b82516001600160401b03811115612da257600080fd5b8301601f81018513612db357600080fd5b8051612dc1611ed682611e92565b81815260059190911b82018301908381019087831115612de057600080fd5b928401925b82841015611c8e578351612df881612039565b82529284019290840190612de5565b6001600160f81b03198b811682528a8116600183015260608a901b6001600160601b031916600283015260c089901b6001600160c01b0319166016830152875160009190612e5c81601e860160208d01612719565b8084019050818960f81b16601e82015287519150612e8182601f830160208b01612719565b8651910190612e9781601f840160208a01612719565b612eaf612ea9601f8385010188612745565b86612745565b9e9d5050505050505050505050505050565b6001600160f81b0319868116825285166001820152606084901b6001600160601b031916600282015260c083901b6001600160c01b03191660168201528151600090612f1481601e850160208701612719565b91909101601e019695505050505050565b600082612f4257634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615612f6157612f61612799565b500290565b60008351612f78818460208801612719565b60c09390931b6001600160c01b0319169190920190815260080192915050565b60008351612faa818460208801612719565b60609390931b6001600160601b0319169190920190815260140192915050565b60008251612fdc818460208701612719565b9190910192915050565b6020815260008251806020840152613005816040850160208701612719565b601f01601f1916919091016040019291505056fea264697066735822122045e2dbf9891287aad543b5bf953d44b537d8c0f931eea8fd459e598853d11ebf64736f6c634300080c0033