Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
AssetManager
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
import "forge-std/console.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "@iconfoundation/xcall-solidity-library/utils/NetworkAddress.sol";
import "@iconfoundation/xcall-solidity-library/utils/Strings.sol";
import "@iconfoundation/xcall-solidity-library/utils/ParseAddress.sol";
import "@iconfoundation/xcall-solidity-library/interfaces/ICallService.sol";
import "@iconfoundation/xcall-solidity-library/interfaces/ICallServiceReceiver.sol";
import "./Messages.sol";
import "./RLPEncodeStruct.sol";
import "./RLPDecodeStruct.sol";
import "../lib/interfaces/IXCallManager.sol";
contract AssetManager is
ICallServiceReceiver,
UUPSUpgradeable,
OwnableUpgradeable
{
using Strings for string;
using NetworkAddress for string;
using ParseAddress for address;
using ParseAddress for string;
using RLPEncodeStruct for Messages.Deposit;
using RLPEncodeStruct for Messages.DepositRevert;
using RLPDecodeStruct for bytes;
using SafeERC20 for IERC20;
address public xCall;
string public xCallNetworkAddress;
string public iconAssetManager;
address public xCallManager;
address public constant NATIVE_ADDRESS = address(0);
mapping(address => uint) public period;
mapping(address => uint) public percentage;
mapping(address => uint) public lastUpdate;
mapping(address => uint) public currentLimit;
uint private constant POINTS = 10000;
function initialize(
address _xCall,
string memory _iconAssetManager,
address _xCallManager
) public initializer {
xCall = _xCall;
xCallNetworkAddress = ICallService(xCall).getNetworkAddress();
iconAssetManager = _iconAssetManager;
xCallManager = _xCallManager;
__Ownable_init(msg.sender);
}
/* ========== UUPS ========== */
//solhint-disable-next-line no-empty-blocks
function _authorizeUpgrade(address) internal override onlyOwner {}
function getImplementation() external view returns (address) {
return ERC1967Utils.getImplementation();
}
modifier onlyCallService() {
require(msg.sender == xCall, "onlyCallService");
_;
}
function configureRateLimit(
address token,
uint _period,
uint _percentage
) external onlyOwner {
require(_percentage <= POINTS,"Percentage should be less than or equal to POINTS");
period[token] = _period;
percentage[token] = _percentage;
lastUpdate[token] = block.timestamp;
currentLimit[token] = (balanceOf(token) * _percentage) / POINTS;
}
function resetLimit(address token) external onlyOwner {
currentLimit[token] = (balanceOf(token) * percentage[token]) / POINTS;
}
function getWithdrawLimit(address token) external view returns (uint) {
uint balance = balanceOf(token);
return calculateLimit(balance, token);
}
function verifyWithdraw(address token, uint amount) internal {
uint balance = balanceOf(token);
uint limit = calculateLimit(balance, token);
require(balance - amount >= limit, "exceeds withdraw limit");
currentLimit[token] = limit;
lastUpdate[token] = block.timestamp;
}
function calculateLimit(uint balance, address token) internal view returns (uint) {
uint _period = period[token];
uint _percentage = percentage[token];
if (_period == 0) {
return 0;
}
uint maxLimit = (balance * _percentage) / POINTS;
// The maximum amount that can be withdraw in one period
uint maxWithdraw = balance - maxLimit;
uint timeDiff = block.timestamp - lastUpdate[token];
timeDiff = Math.min(timeDiff, _period);
// The amount that should be added as availbe
uint addedAllowedWithdrawal = (maxWithdraw * timeDiff) / _period;
uint limit = currentLimit[token] - addedAllowedWithdrawal;
// If the balance is below the limit then set limt to current balance (no withdraws are possible)
limit = Math.min(balance, limit);
// If limit goes below what the protected percentage is set it to the maxLimit
return Math.max(limit, maxLimit);
}
function deposit(address token, uint amount) external payable {
_deposit(token, amount, "", "");
}
function deposit(
address token,
uint amount,
string memory to
) external payable {
_deposit(token, amount, to, "");
}
function deposit(
address token,
uint amount,
string memory to,
bytes memory data
) external payable {
_deposit(token, amount, to, data);
}
function depositNative(uint amount) external payable {
_depositNative(amount, "", "");
}
function depositNative(uint amount, string memory to) external payable {
_depositNative(amount, to, "");
}
function depositNative(
uint amount,
string memory to,
bytes memory data
) external payable {
_depositNative(amount, to, data);
}
function _deposit(
address token,
uint amount,
string memory to,
bytes memory data
) internal {
require(amount >= 0, "Amount less than minimum amount");
IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
sendDepositMessage(token, amount, to, data, msg.value);
}
function _depositNative(
uint amount,
string memory to,
bytes memory data
) internal {
require(msg.value >= amount, "Amount less than minimum amount");
uint fee = msg.value - amount;
sendDepositMessage(NATIVE_ADDRESS, amount, to, data, fee);
}
function sendDepositMessage(
address token,
uint amount,
string memory to,
bytes memory data,
uint fee
) internal {
Messages.Deposit memory xcallMessage = Messages.Deposit(
token.toString(),
msg.sender.toString(),
to,
amount,
data
);
Messages.DepositRevert memory rollback = Messages.DepositRevert(
token,
amount,
msg.sender
);
IXCallManager.Protocols memory protocols = IXCallManager(xCallManager)
.getProtocols();
ICallService(xCall).sendCallMessage{value: fee}(
iconAssetManager,
xcallMessage.encodeDeposit(),
rollback.encodeDepositRevert(),
protocols.sources,
protocols.destinations
);
}
function handleCallMessage(
string calldata from,
bytes calldata data,
string[] calldata protocols
) external onlyCallService {
require(
IXCallManager(xCallManager).verifyProtocols(protocols),
"Protocol Mismatch"
);
string memory method = data.getMethod();
if (method.compareTo(Messages.WITHDRAW_TO_NAME)) {
require(from.compareTo(iconAssetManager), "onlyICONAssetManager");
Messages.WithdrawTo memory message = data.decodeWithdrawTo();
withdraw(
message.tokenAddress.parseAddress("Invalid account"),
message.to.parseAddress("Invalid account"),
message.amount
);
} else if (method.compareTo(Messages.WITHDRAW_NATIVE_TO_NAME)) {
revert("Withdraw to native is currently not supported");
} else if (method.compareTo(Messages.DEPOSIT_REVERT_NAME)) {
require(from.compareTo(xCallNetworkAddress), "onlyCallService");
Messages.DepositRevert memory message = data.decodeDepositRevert();
withdraw(message.tokenAddress, message.to, message.amount);
} else {
revert("Unknown message type");
}
}
function withdraw(address token, address to, uint amount) internal {
require(amount > 0, "Amount less than minimum amount");
verifyWithdraw(token, amount);
if (token == NATIVE_ADDRESS) {
bool sent = payable(to).send(amount);
require(sent, "Failed to send tokens");
} else {
IERC20(token).safeTransfer(to, amount);
}
}
function balanceOf(address token) internal view returns (uint) {
if (token == NATIVE_ADDRESS) {
return address(this).balance;
}
return IERC20(token).balanceOf(address(this));
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
library console {
address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);
function _sendLogPayload(bytes memory payload) private view {
uint256 payloadLength = payload.length;
address consoleAddress = CONSOLE_ADDRESS;
/// @solidity memory-safe-assembly
assembly {
let payloadStart := add(payload, 32)
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
}
}
function log() internal view {
_sendLogPayload(abi.encodeWithSignature("log()"));
}
function logInt(int p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
}
function logUint(uint p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
}
function logString(string memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function logBool(bool p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function logAddress(address p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function logBytes(bytes memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
}
function logBytes1(bytes1 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
}
function logBytes2(bytes2 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
}
function logBytes3(bytes3 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
}
function logBytes4(bytes4 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
}
function logBytes5(bytes5 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
}
function logBytes6(bytes6 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
}
function logBytes7(bytes7 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
}
function logBytes8(bytes8 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
}
function logBytes9(bytes9 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
}
function logBytes10(bytes10 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
}
function logBytes11(bytes11 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
}
function logBytes12(bytes12 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
}
function logBytes13(bytes13 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
}
function logBytes14(bytes14 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
}
function logBytes15(bytes15 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
}
function logBytes16(bytes16 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
}
function logBytes17(bytes17 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
}
function logBytes18(bytes18 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
}
function logBytes19(bytes19 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
}
function logBytes20(bytes20 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
}
function logBytes21(bytes21 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
}
function logBytes22(bytes22 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
}
function logBytes23(bytes23 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
}
function logBytes24(bytes24 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
}
function logBytes25(bytes25 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
}
function logBytes26(bytes26 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
}
function logBytes27(bytes27 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
}
function logBytes28(bytes28 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
}
function logBytes29(bytes29 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
}
function logBytes30(bytes30 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
}
function logBytes31(bytes31 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
}
function logBytes32(bytes32 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
}
function log(uint p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
}
function log(string memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function log(bool p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function log(address p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function log(uint p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
}
function log(uint p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
}
function log(uint p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
}
function log(uint p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
}
function log(string memory p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
}
function log(string memory p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
function log(string memory p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
}
function log(string memory p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
}
function log(bool p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
}
function log(bool p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
}
function log(bool p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
}
function log(bool p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
}
function log(address p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
}
function log(address p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
}
function log(address p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
}
function log(address p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
}
function log(uint p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
}
function log(uint p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
}
function log(uint p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
}
function log(uint p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
}
function log(uint p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
}
function log(uint p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
}
function log(uint p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
}
function log(uint p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
}
function log(uint p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
}
function log(uint p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
}
function log(uint p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
}
function log(uint p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
}
function log(uint p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
}
function log(uint p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
}
function log(uint p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
}
function log(uint p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
}
function log(string memory p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
}
function log(string memory p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
}
function log(string memory p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
}
function log(string memory p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
}
function log(string memory p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
}
function log(string memory p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
}
function log(string memory p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
}
function log(string memory p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
}
function log(string memory p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
}
function log(string memory p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
}
function log(string memory p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
}
function log(string memory p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
}
function log(string memory p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
}
function log(string memory p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
}
function log(string memory p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
}
function log(bool p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
}
function log(bool p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
}
function log(bool p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
}
function log(bool p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
}
function log(bool p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
}
function log(bool p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
}
function log(bool p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
}
function log(bool p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
}
function log(bool p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
}
function log(bool p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
}
function log(bool p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
}
function log(bool p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
}
function log(bool p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
}
function log(bool p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
}
function log(bool p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
}
function log(address p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
}
function log(address p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
}
function log(address p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
}
function log(address p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
}
function log(address p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
}
function log(address p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
}
function log(address p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
}
function log(address p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
}
function log(address p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
}
function log(address p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
}
function log(address p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
}
function log(address p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
}
function log(address p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
}
function log(address p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
}
function log(address p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
}
function log(uint p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @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 value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` 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 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @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);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @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).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// 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 cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.20;
import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol";
import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol";
import {Initializable} from "./Initializable.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*/
abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address private immutable __self = address(this);
/**
* @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`
* and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,
* while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.
* If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must
* be the empty byte string if no function should be called, making it impossible to invoke the `receive` function
* during an upgrade.
*/
string public constant UPGRADE_INTERFACE_VERSION = "5.0.0";
/**
* @dev The call is from an unauthorized context.
*/
error UUPSUnauthorizedCallContext();
/**
* @dev The storage `slot` is unsupported as a UUID.
*/
error UUPSUnsupportedProxiableUUID(bytes32 slot);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
_checkProxy();
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
_checkNotDelegated();
_;
}
function __UUPSUpgradeable_init() internal onlyInitializing {
}
function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
}
/**
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual notDelegated returns (bytes32) {
return ERC1967Utils.IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data);
}
/**
* @dev Reverts if the execution is not performed via delegatecall or the execution
* context is not of a proxy with an ERC1967-compliant implementation pointing to self.
* See {_onlyProxy}.
*/
function _checkProxy() internal view virtual {
if (
address(this) == __self || // Must be called through delegatecall
ERC1967Utils.getImplementation() != __self // Must be called through an active proxy
) {
revert UUPSUnauthorizedCallContext();
}
}
/**
* @dev Reverts if the execution is performed via delegatecall.
* See {notDelegated}.
*/
function _checkNotDelegated() internal view virtual {
if (address(this) != __self) {
// Must not be called through delegatecall
revert UUPSUnauthorizedCallContext();
}
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
/**
* @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.
*
* As a security check, {proxiableUUID} is invoked in the new implementation, and the return value
* is expected to be the implementation slot in ERC1967.
*
* Emits an {IERC1967-Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {
revert UUPSUnsupportedProxiableUUID(slot);
}
ERC1967Utils.upgradeToAndCall(newImplementation, data);
} catch {
// The implementation is not UUPS
revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.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.
*
* The initial owner is set to the address provided by the deployer. 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 {
/// @custom:storage-location erc7201:openzeppelin.storage.Ownable
struct OwnableStorage {
address _owner;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;
function _getOwnableStorage() private pure returns (OwnableStorage storage $) {
assembly {
$.slot := OwnableStorageLocation
}
}
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
function __Ownable_init(address initialOwner) internal onlyInitializing {
__Ownable_init_unchained(initialOwner);
}
function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @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) {
OwnableStorage storage $ = _getOwnableStorage();
return $._owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling 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 {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
OwnableStorage storage $ = _getOwnableStorage();
address oldOwner = $._owner;
$._owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol)
pragma solidity ^0.8.20;
import {IBeacon} from "../beacon/IBeacon.sol";
import {Address} from "../../utils/Address.sol";
import {StorageSlot} from "../../utils/StorageSlot.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*/
library ERC1967Utils {
// We re-declare ERC-1967 events here because they can't be used directly from IERC1967.
// This will be fixed in Solidity 0.8.21. At that point we should remove these events.
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev The `implementation` of the proxy is invalid.
*/
error ERC1967InvalidImplementation(address implementation);
/**
* @dev The `admin` of the proxy is invalid.
*/
error ERC1967InvalidAdmin(address admin);
/**
* @dev The `beacon` of the proxy is invalid.
*/
error ERC1967InvalidBeacon(address beacon);
/**
* @dev An upgrade function sees `msg.value > 0` that may be lost.
*/
error ERC1967NonPayable();
/**
* @dev Returns the current implementation address.
*/
function getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
if (newImplementation.code.length == 0) {
revert ERC1967InvalidImplementation(newImplementation);
}
StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Performs implementation upgrade with additional setup call if data is nonempty.
* This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
* to avoid stuck value in the contract.
*
* Emits an {IERC1967-Upgraded} event.
*/
function upgradeToAndCall(address newImplementation, bytes memory data) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
if (data.length > 0) {
Address.functionDelegateCall(newImplementation, data);
} else {
_checkNonPayable();
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*
* TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using
* the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
* `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
*/
function getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
if (newAdmin == address(0)) {
revert ERC1967InvalidAdmin(address(0));
}
StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {IERC1967-AdminChanged} event.
*/
function changeAdmin(address newAdmin) internal {
emit AdminChanged(getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
if (newBeacon.code.length == 0) {
revert ERC1967InvalidBeacon(newBeacon);
}
StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;
address beaconImplementation = IBeacon(newBeacon).implementation();
if (beaconImplementation.code.length == 0) {
revert ERC1967InvalidImplementation(beaconImplementation);
}
}
/**
* @dev Change the beacon and trigger a setup call if data is nonempty.
* This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
* to avoid stuck value in the contract.
*
* Emits an {IERC1967-BeaconUpgraded} event.
*
* CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since
* it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for
* efficiency.
*/
function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
} else {
_checkNonPayable();
}
}
/**
* @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract
* if an upgrade doesn't perform an initialization call.
*/
function _checkNonPayable() private {
if (msg.value > 0) {
revert ERC1967NonPayable();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @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 towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
return a / b;
}
// (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 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 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.
uint256 twos = denominator & (0 - denominator);
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 (unsignedRoundsUp(rounding) && 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
* towards zero.
*
* 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 + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* 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 + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* 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 + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* 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 256, 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 + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
/**
NetworkAdress 'NETWORK_ID/ACCOUNT_ADDRESS'
*/
library NetworkAddress {
string internal constant REVERT = "invalidNetworkAddress";
bytes internal constant DELIMITER = bytes("/");
/**
@notice Parse NetworkAddress address
@param _str (String) Network Address
@return (String) network id
@return (String) account address
*/
function parseNetworkAddress(
string memory _str
) internal pure returns (
string memory,
string memory
) {
uint256 offset = _validate(_str);
return (_slice(_str, 0, offset),
_slice(_str, offset+1, bytes(_str).length));
}
/**
@notice Gets network id of Network address
@param _str (String) Network address
@return (String) network id
*/
function nid(
string memory _str
) internal pure returns (
string memory
) {
return _slice(_str, 0, _validate(_str));
}
function _validate(
string memory _str
) private pure returns (
uint256 offset
){
bytes memory _bytes = bytes(_str);
uint256 i = 0;
for (; i < _bytes.length; i++) {
if (_bytes[i] == DELIMITER[0]) {
require(i > 6 && i < (_bytes.length -1), REVERT);
return i;
}
}
revert(REVERT);
}
function _slice(
string memory _str,
uint256 _from,
uint256 _to
) private pure returns (
string memory
) {
//If _str is calldata, could use slice
// return string(bytes(_str)[_from:_to]);
bytes memory _bytes = bytes(_str);
bytes memory _ret = new bytes(_to - _from);
uint256 j = _from;
for (uint256 i = 0; i < _ret.length; i++) {
_ret[i] = _bytes[j++];
}
return string(_ret);
}
/**
@notice Create Network address by network id and account address
@param _net (String) network id
@param _addr (String) account address
@return (String) Network address
*/
function networkAddress(
string memory _net,
string memory _addr
) internal pure returns (
string memory
) {
return string(abi.encodePacked(_net, DELIMITER, _addr));
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
/**
* Strings Library
*
* This is a simple library of string functions which try to simplify
* string operations in solidity.
*
* Please be aware some of these functions can be quite gas heavy so use them only when necessary
*
* The original library was modified. If you want to know more about the original version
* please check this link: https://github.com/willitscale/solidity-util.git
*/
library Strings {
/**
* splitBTPAddress
*
* Split the BTP Address format i.e. btp://1234.iconee/0x123456789
* into Network_address (1234.iconee) and Server_address (0x123456789)
*
* @param _base String base BTP Address format to be split
* @dev _base must follow a BTP Address format
*
* @return string, string The resulting strings of Network_address and Server_address
*/
function splitBTPAddress(string memory _base)
internal
pure
returns (string memory, string memory)
{
string[] memory temp = split(_base, "/");
return (temp[2], temp[3]);
}
function bytesToHex(bytes memory buffer) internal pure returns (string memory) {
if (buffer.length == 0) {
return string("0x");
}
// Fixed buffer size for hexadecimal convertion
bytes memory converted = new bytes(buffer.length * 2);
bytes memory _base = "0123456789abcdef";
for (uint256 i = 0; i < buffer.length; i++) {
converted[i * 2] = _base[uint8(buffer[i]) >> 4 & 0xf];
converted[i * 2 + 1] = _base[uint8(buffer[i]) & 0xf];
}
return string(abi.encodePacked("0x", converted));
}
/**
* Concat
*
* Appends two strings together and returns a new value
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string which will be the concatenated
* prefix
* @param _value The value to be the concatenated suffix
* @return string The resulting string from combinging the base and value
*/
function concat(string memory _base, string memory _value)
internal
pure
returns (string memory)
{
return string(abi.encodePacked(_base, _value));
}
/**
* Index Of
*
* Locates and returns the position of a character within a string
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string acting as the haystack to be
* searched
* @param _value The needle to search for, at present this is currently
* limited to one character
* @return int The position of the needle starting from 0 and returning -1
* in the case of no matches found
*/
function indexOf(string memory _base, string memory _value)
internal
pure
returns (int256)
{
return _indexOf(_base, _value, 0);
}
/**
* Index Of
*
* Locates and returns the position of a character within a string starting
* from a defined offset
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string acting as the haystack to be
* searched
* @param _value The needle to search for, at present this is currently
* limited to one character
* @param _offset The starting point to start searching from which can start
* from 0, but must not exceed the length of the string
* @return int The position of the needle starting from 0 and returning -1
* in the case of no matches found
*/
function _indexOf(
string memory _base,
string memory _value,
uint256 _offset
) internal pure returns (int256) {
bytes memory _baseBytes = bytes(_base);
bytes memory _valueBytes = bytes(_value);
assert(_valueBytes.length == 1);
for (uint256 i = _offset; i < _baseBytes.length; i++) {
if (_baseBytes[i] == _valueBytes[0]) {
return int256(i);
}
}
return -1;
}
/**
* Length
*
* Returns the length of the specified string
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string to be measured
* @return uint The length of the passed string
*/
function length(string memory _base) internal pure returns (uint256) {
bytes memory _baseBytes = bytes(_base);
return _baseBytes.length;
}
/*
* String Split (Very high gas cost)
*
* Splits a string into an array of strings based off the delimiter value.
* Please note this can be quite a gas expensive function due to the use of
* storage so only use if really required.
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string value to be split.
* @param _value The delimiter to split the string on which must be a single
* character
* @return string[] An array of values split based off the delimiter, but
* do not container the delimiter.
*/
function split(string memory _base, string memory _value)
internal
pure
returns (string[] memory splitArr)
{
bytes memory _baseBytes = bytes(_base);
uint256 _offset = 0;
uint256 _splitsCount = 1;
while (_offset < _baseBytes.length - 1) {
int256 _limit = _indexOf(_base, _value, _offset);
if (_limit == -1) break;
else {
_splitsCount++;
_offset = uint256(_limit) + 1;
}
}
splitArr = new string[](_splitsCount);
_offset = 0;
_splitsCount = 0;
while (_offset < _baseBytes.length - 1) {
int256 _limit = _indexOf(_base, _value, _offset);
if (_limit == -1) {
_limit = int256(_baseBytes.length);
}
string memory _tmp = new string(uint256(_limit) - _offset);
bytes memory _tmpBytes = bytes(_tmp);
uint256 j = 0;
for (uint256 i = _offset; i < uint256(_limit); i++) {
_tmpBytes[j++] = _baseBytes[i];
}
_offset = uint256(_limit) + 1;
splitArr[_splitsCount++] = string(_tmpBytes);
}
return splitArr;
}
/**
* Compare To
*
* Compares the characters of two strings, to ensure that they have an
* identical footprint
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string base to compare against
* @param _value The string the base is being compared to
* @return bool Simply notates if the two string have an equivalent
*/
function compareTo(string memory _base, string memory _value)
internal
pure
returns (bool)
{
if (
keccak256(abi.encodePacked(_base)) ==
keccak256(abi.encodePacked(_value))
) {
return true;
}
return false;
}
/**
* Lower
*
* Converts all the values of a string to their corresponding lower case
* value.
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string base to convert to lower case
* @return string
*/
function lower(string memory _base)
internal
pure
returns (string memory) {
bytes memory _baseBytes = bytes(_base);
for (uint i = 0; i < _baseBytes.length; i++) {
_baseBytes[i] = _lower(_baseBytes[i]);
}
return string(_baseBytes);
}
/**
* Lower
*
* Convert an alphabetic character to lower case and return the original
* value when not alphabetic
*
* @param _b1 The byte to be converted to lower case
* @return bytes1 The converted value if the passed value was alphabetic
* and in a upper case otherwise returns the original value
*/
function _lower(bytes1 _b1)
private
pure
returns (bytes1) {
if (_b1 >= 0x41 && _b1 <= 0x5A) {
return bytes1(uint8(_b1) + 32);
}
return _b1;
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
/*
* Utility library of inline functions on addresses
*/
library ParseAddress {
/**
* @dev Get a checksummed string hex representation of an account address.
* @param account address The account to get the checksum for.
* @return The checksummed account string in ASCII format. Note that leading
* "0x" is not included.
*/
function toString(address account) internal pure returns (string memory) {
// call internal function for converting an account to a checksummed string.
return _toChecksumString(account);
}
/**
* @dev Get a fixed-size array of whether or not each character in an account
* will be capitalized in the checksum.
* @param account address The account to get the checksum capitalization
* information for.
* @return A fixed-size array of booleans that signify if each character or
* "nibble" of the hex encoding of the address will be capitalized by the
* checksum.
*/
function getChecksumCapitalizedCharacters(address account)
internal
pure
returns (bool[40] memory)
{
// call internal function for computing characters capitalized in checksum.
return _toChecksumCapsFlags(account);
}
/**
* @dev Determine whether a string hex representation of an account address
* matches the ERC-55 checksum of that address.
* @param accountChecksum string The checksummed account string in ASCII
* format. Note that a leading "0x" MUST NOT be included.
* @return A boolean signifying whether or not the checksum is valid.
*/
function isChecksumValid(string calldata accountChecksum)
internal
pure
returns (bool)
{
// call internal function for validating checksum strings.
return _isChecksumValid(accountChecksum);
}
function _toChecksumString(address account)
internal
pure
returns (string memory asciiString)
{
// convert the account argument from address to bytes.
bytes20 data = bytes20(account);
// create an in-memory fixed-size bytes array.
bytes memory asciiBytes = new bytes(40);
// declare variable types.
uint8 b;
uint8 leftNibble;
uint8 rightNibble;
bool leftCaps;
bool rightCaps;
uint8 asciiOffset;
// get the capitalized characters in the actual checksum.
bool[40] memory caps = _toChecksumCapsFlags(account);
// iterate over bytes, processing left and right nibble in each iteration.
for (uint256 i = 0; i < data.length; i++) {
// locate the byte and extract each nibble.
b = uint8(uint160(data) / (2**(8 * (19 - i))));
leftNibble = b / 16;
rightNibble = b - 16 * leftNibble;
// locate and extract each capitalization status.
leftCaps = caps[2 * i];
rightCaps = caps[2 * i + 1];
// get the offset from nibble value to ascii character for left nibble.
asciiOffset = _getAsciiOffset(leftNibble, leftCaps);
// add the converted character to the byte array.
asciiBytes[2 * i] = bytes1(leftNibble + asciiOffset);
// get the offset from nibble value to ascii character for right nibble.
asciiOffset = _getAsciiOffset(rightNibble, rightCaps);
// add the converted character to the byte array.
asciiBytes[2 * i + 1] = bytes1(rightNibble + asciiOffset);
}
return string(abi.encodePacked("0x", string(asciiBytes)));
}
function _toChecksumCapsFlags(address account)
internal
pure
returns (bool[40] memory characterCapitalized)
{
// convert the address to bytes.
bytes20 a = bytes20(account);
// hash the address (used to calculate checksum).
bytes32 b = keccak256(abi.encodePacked(_toAsciiString(a)));
// declare variable types.
uint8 leftNibbleAddress;
uint8 rightNibbleAddress;
uint8 leftNibbleHash;
uint8 rightNibbleHash;
// iterate over bytes, processing left and right nibble in each iteration.
for (uint256 i; i < a.length; i++) {
// locate the byte and extract each nibble for the address and the hash.
rightNibbleAddress = uint8(a[i]) % 16;
leftNibbleAddress = (uint8(a[i]) - rightNibbleAddress) / 16;
rightNibbleHash = uint8(b[i]) % 16;
leftNibbleHash = (uint8(b[i]) - rightNibbleHash) / 16;
characterCapitalized[2 * i] = (leftNibbleAddress > 9 &&
leftNibbleHash > 7);
characterCapitalized[2 * i + 1] = (rightNibbleAddress > 9 &&
rightNibbleHash > 7);
}
}
function _isChecksumValid(string memory provided)
internal
pure
returns (bool ok)
{
// convert the provided string into account type.
address account = _toAddress(provided);
// return false in the event the account conversion returned null address.
if (account == address(0)) {
// ensure that provided address is not also the null address first.
bytes memory b = bytes(provided);
for (uint256 i; i < b.length; i++) {
if (b[i] != hex"30") {
return false;
}
}
}
// get the capitalized characters in the actual checksum.
string memory actual = _toChecksumString(account);
// compare provided string to actual checksum string to test for validity.
return (keccak256(abi.encodePacked(actual)) ==
keccak256(abi.encodePacked(provided)));
}
function _getAsciiOffset(uint8 nibble, bool caps)
internal
pure
returns (uint8 offset)
{
// to convert to ascii characters, add 48 to 0-9, 55 to A-F, & 87 to a-f.
if (nibble < 10) {
offset = 48;
} else if (caps) {
offset = 55;
} else {
offset = 87;
}
}
function _toAddress(string memory account)
internal
pure
returns (address accountAddress)
{
// convert the account argument from address to bytes.
bytes memory accountBytes = bytes(account);
// create a new fixed-size byte array for the ascii bytes of the address.
bytes memory accountAddressBytes = new bytes(20);
// declare variable types.
uint8 b;
uint8 nibble;
uint8 asciiOffset;
// only proceed if the provided string has a length of 40.
if (accountBytes.length == 40) {
for (uint256 i; i < 40; i++) {
// get the byte in question.
b = uint8(accountBytes[i]);
// ensure that the byte is a valid ascii character (0-9, A-F, a-f)
if (b < 48) return address(0);
if (57 < b && b < 65) return address(0);
if (70 < b && b < 97) return address(0);
if (102 < b) return address(0); //bytes(hex"");
// find the offset from ascii encoding to the nibble representation.
if (b < 65) {
// 0-9
asciiOffset = 48;
} else if (70 < b) {
// a-f
asciiOffset = 87;
} else {
// A-F
asciiOffset = 55;
}
// store left nibble on even iterations, then store byte on odd ones.
if (i % 2 == 0) {
nibble = b - asciiOffset;
} else {
accountAddressBytes[(i - 1) / 2] = (
bytes1(16 * nibble + (b - asciiOffset))
);
}
}
// pack up the fixed-size byte array and cast it to accountAddress.
bytes memory packed = abi.encodePacked(accountAddressBytes);
assembly {
accountAddress := mload(add(packed, 20))
}
}
}
// based on https://ethereum.stackexchange.com/a/56499/48410
function _toAsciiString(bytes20 data)
internal
pure
returns (string memory asciiString)
{
// create an in-memory fixed-size bytes array.
bytes memory asciiBytes = new bytes(40);
// declare variable types.
uint8 b;
uint8 leftNibble;
uint8 rightNibble;
// iterate over bytes, processing left and right nibble in each iteration.
for (uint256 i = 0; i < data.length; i++) {
// locate the byte and extract each nibble.
b = uint8(uint160(data) / (2**(8 * (19 - i))));
leftNibble = b / 16;
rightNibble = b - 16 * leftNibble;
// to convert to ascii characters, add 48 to 0-9 and 87 to a-f.
asciiBytes[2 * i] = bytes1(
leftNibble + (leftNibble < 10 ? 48 : 87)
);
asciiBytes[2 * i + 1] = bytes1(
rightNibble + (rightNibble < 10 ? 48 : 87)
);
}
return string(asciiBytes);
}
function parseAddress(
string memory account,
string memory revertMsg
) internal pure returns (address accountAddress)
{
bytes memory accountBytes = bytes(account);
require(
accountBytes.length == 42 &&
accountBytes[0] == bytes1("0") &&
accountBytes[1] == bytes1("x"),
revertMsg
);
// create a new fixed-size byte array for the ascii bytes of the address.
bytes memory accountAddressBytes = new bytes(20);
// declare variable types.
uint8 b;
uint8 nibble;
uint8 asciiOffset;
for (uint256 i = 0; i < 40; i++) {
// get the byte in question.
b = uint8(accountBytes[i + 2]);
bool isValidASCII = true;
// ensure that the byte is a valid ascii character (0-9, A-F, a-f)
if (b < 48) isValidASCII = false;
if (57 < b && b < 65) isValidASCII = false;
if (70 < b && b < 97) isValidASCII = false;
if (102 < b) isValidASCII = false; //bytes(hex"");
// If string contains invalid ASCII characters, revert()
if (!isValidASCII) revert(revertMsg);
// find the offset from ascii encoding to the nibble representation.
if (b < 65) {
// 0-9
asciiOffset = 48;
} else if (70 < b) {
// a-f
asciiOffset = 87;
} else {
// A-F
asciiOffset = 55;
}
// store left nibble on even iterations, then store byte on odd ones.
if (i % 2 == 0) {
nibble = b - asciiOffset;
} else {
accountAddressBytes[(i - 1) / 2] = (
bytes1(16 * nibble + (b - asciiOffset))
);
}
}
// pack up the fixed-size byte array and cast it to accountAddress.
bytes memory packed = abi.encodePacked(accountAddressBytes);
assembly {
accountAddress := mload(add(packed, 20))
}
// return false in the event the account conversion returned null address.
if (accountAddress == address(0)) {
// ensure that provided address is not also the null address first.
for (uint256 i = 2; i < accountBytes.length; i++)
require(accountBytes[i] == hex"30", revertMsg);
}
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
interface ICallService {
function getNetworkAddress(
) external view returns (
string memory
);
function getNetworkId(
) external view returns (
string memory
);
/**
@notice Gets the fee for delivering a message to the _net.
If the sender is going to provide rollback data, the _rollback param should set as true.
The returned fee is the sum of the protocol fee and the relay fee.
@param _net (String) The destination network address
@param _rollback (Bool) Indicates whether it provides rollback data
@return (Integer) the sum of the protocol fee and the relay fee
*/
function getFee(
string memory _net,
bool _rollback
) external view returns (
uint256
);
function getFee(
string memory _net,
bool _rollback,
string[] memory _sources
) external view returns (
uint256
);
/*======== At the source CALL_BSH ========*/
/**
@notice Sends a call message to the contract on the destination chain.
@param _to The BTP address of the callee on the destination chain
@param _data The calldata specific to the target contract
@param _rollback (Optional) The data for restoring the caller state when an error occurred
@return The serial number of the request
*/
function sendCallMessage(
string memory _to,
bytes memory _data,
bytes memory _rollback,
string[] memory sources,
string[] memory destinations
) external payable returns (
uint256
);
/**
@notice Notifies that the requested call message has been sent.
@param _from The chain-specific address of the caller
@param _to The BTP address of the callee on the destination chain
@param _sn The serial number of the request
*/
event CallMessageSent(
address indexed _from,
string indexed _to,
uint256 indexed _sn
);
/**
@notice Notifies that a response message has arrived for the `_sn` if the request was a two-way message.
@param _sn The serial number of the previous request
@param _code The execution result code
(0: Success, -1: Unknown generic failure, >=1: User defined error code)
*/
event ResponseMessage(
uint256 indexed _sn,
int _code
);
/**
@notice Notifies the user that a rollback operation is required for the request '_sn'.
@param _sn The serial number of the previous request
*/
event RollbackMessage(
uint256 indexed _sn
);
/**
@notice Rollbacks the caller state of the request '_sn'.
@param _sn The serial number of the previous request
*/
function executeRollback(
uint256 _sn
) external;
/**
@notice Notifies that the rollback has been executed.
@param _sn The serial number for the rollback
*/
event RollbackExecuted(
uint256 indexed _sn
);
/*======== At the destination CALL_BSH ========*/
/**
@notice Notifies the user that a new call message has arrived.
@param _from The BTP address of the caller on the source chain
@param _to A string representation of the callee address
@param _sn The serial number of the request from the source
@param _reqId The request id of the destination chain
@param _data The calldata
*/
event CallMessage(
string indexed _from,
string indexed _to,
uint256 indexed _sn,
uint256 _reqId,
bytes _data
);
/**
@notice Executes the requested call message.
@param _reqId The request id
@param _data The calldata
*/
function executeCall(
uint256 _reqId,
bytes memory _data
) external;
/**
@notice Notifies that the call message has been executed.
@param _reqId The request id for the call message
@param _code The execution result code
(0: Success, -1: Unknown generic failure)
@param _msg The result message if any
*/
event CallExecuted(
uint256 indexed _reqId,
int _code,
string _msg
);
/**
@notice BTP Message from other blockchain.
@param _from Network Address of source network
@param _msg Serialized bytes of ServiceMessage
*/
function handleMessage(
string calldata _from,
bytes calldata _msg
) external;
/**
@notice Handle the error on delivering the message.
@param _sn Serial number of the original message
*/
function handleError(
uint256 _sn
) external;
}// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
interface ICallServiceReceiver {
/**
@notice Handles the call message received from the source chain.
@dev Only called from the Call Message Service.
@param _from The BTP address of the caller on the source chain
@param _data The calldata delivered from the caller
@param _protocols The addresses that delivered the message
*/
function handleCallMessage(
string calldata _from,
bytes calldata _data,
string[] calldata _protocols
) external;
}// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
/**
* @notice List of ALL Struct being used to Encode and Decode RLP Messages
*/
library Messages {
string constant DEPOSIT_NAME = "Deposit";
struct Deposit {
string tokenAddress;
string from;
string to;
uint amount;
bytes data;
}
string constant DEPOSIT_REVERT_NAME = "DepositRevert";
struct DepositRevert {
address tokenAddress;
uint amount;
address to;
}
string constant WITHDRAW_TO_NAME = "WithdrawTo";
struct WithdrawTo {
string tokenAddress;
string to;
uint amount;
}
string constant WITHDRAW_NATIVE_TO_NAME = "WithdrawNativeTo";
}// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
pragma abicoder v2;
import "@iconfoundation/xcall-solidity-library/utils/RLPEncode.sol";
import "./Messages.sol";
library RLPEncodeStruct {
using RLPEncode for bytes;
using RLPEncode for string;
using RLPEncode for uint256;
using RLPEncode for int256;
using RLPEncode for address;
using RLPEncode for bool;
function encodeDeposit(
Messages.Deposit memory message
) internal pure returns (bytes memory) {
bytes memory _rlp = abi.encodePacked(
Messages.DEPOSIT_NAME.encodeString(),
message.tokenAddress.encodeString(),
message.from.encodeString(),
message.to.encodeString(),
message.amount.encodeUint(),
message.data.encodeBytes()
);
return _rlp.encodeList();
}
function encodeDepositRevert(
Messages.DepositRevert memory message
) internal pure returns (bytes memory) {
bytes memory _rlp = abi.encodePacked(
Messages.DEPOSIT_REVERT_NAME.encodeString(),
message.tokenAddress.encodeAddress(),
message.amount.encodeUint(),
message.to.encodeAddress()
);
return _rlp.encodeList();
}
function encodeWithdrawTo(
Messages.WithdrawTo memory message
) internal pure returns (bytes memory) {
bytes memory _rlp = abi.encodePacked(
Messages.WITHDRAW_TO_NAME.encodeString(),
message.tokenAddress.encodeString(),
message.to.encodeString(),
message.amount.encodeUint()
);
return _rlp.encodeList();
}
function encodeWithdrawNativeTo(
Messages.WithdrawTo memory message
) internal pure returns (bytes memory) {
bytes memory _rlp = abi.encodePacked(
Messages.WITHDRAW_NATIVE_TO_NAME.encodeString(),
message.tokenAddress.encodeString(),
message.to.encodeString(),
message.amount.encodeUint()
);
return _rlp.encodeList();
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
pragma abicoder v2;
import "@iconfoundation/xcall-solidity-library/utils/RLPDecode.sol";
import "./Messages.sol";
library RLPDecodeStruct {
using RLPDecode for RLPDecode.RLPItem;
using RLPDecode for RLPDecode.Iterator;
using RLPDecode for bytes;
using RLPDecodeStruct for bytes;
uint8 private constant LIST_SHORT_START = 0xc0;
uint8 private constant LIST_LONG_START = 0xf7;
function getMethod(
bytes memory _rlp
) internal pure returns (string memory) {
RLPDecode.RLPItem[] memory ls = _rlp.toRlpItem().toList();
return string(ls[0].toBytes());
}
function decodeDeposit(
bytes memory _rlp
) internal pure returns (Messages.Deposit memory) {
RLPDecode.RLPItem[] memory ls = _rlp.toRlpItem().toList();
return
Messages.Deposit(
string(ls[1].toBytes()),
string(ls[2].toBytes()),
string(ls[3].toBytes()),
ls[4].toUint(),
ls[5].toBytes()
);
}
function decodeDepositRevert(
bytes memory _rlp
) internal pure returns (Messages.DepositRevert memory) {
RLPDecode.RLPItem[] memory ls = _rlp.toRlpItem().toList();
return
Messages.DepositRevert(
ls[1].toAddress(),
ls[2].toUint(),
ls[3].toAddress()
);
}
function decodeWithdrawTo(
bytes memory _rlp
) internal pure returns (Messages.WithdrawTo memory) {
RLPDecode.RLPItem[] memory ls = _rlp.toRlpItem().toList();
return
Messages.WithdrawTo(
string(ls[1].toBytes()),
string(ls[2].toBytes()),
ls[3].toUint()
);
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
interface IXCallManager {
struct Protocols {
string[] sources;
string[] destinations;
}
function getProtocols() external view returns (Protocols memory protocols);
function verifyProtocols(
string[] calldata protocols
) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @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 or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* 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.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @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`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) private pure {
// 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
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.20;
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822Proxiable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.20;
/**
* @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 proxied contracts do not make use of 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.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* 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 prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/
struct InitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/
uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reininitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;
if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$._initialized = 1;
if (isTopLevelCall) {
$._initializing = true;
}
_;
if (isTopLevelCall) {
$._initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._initialized = version;
$._initializing = true;
_;
$._initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/
function _checkInitializing() internal view virtual {
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized != type(uint64).max) {
$._initialized = type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
assembly {
$.slot := INITIALIZABLE_STORAGE
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)
pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @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 onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
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 v5.0.0) (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.20;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeacon {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {UpgradeableBeacon} will check that this address is a contract.
*/
function implementation() external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.20;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
/**
* @title RLPEncode
* @dev A simple RLP encoding library.
* @author Bakaoh
* The original code was modified. For more info, please check the link:
* https://github.com/bakaoh/solidity-rlp-encode.git
*/
library RLPEncode {
bytes internal constant NULL = hex"f800";
/*
* Internal functions
*/
/**
* @dev RLP encodes a byte string.
* @param self The byte string to encode.
* @return The RLP encoded string in bytes.
*/
function encodeBytes(bytes memory self)
internal
pure
returns (bytes memory)
{
bytes memory encoded;
if (self.length == 1 && uint8(self[0]) < 128) {
encoded = self;
} else {
encoded = abi.encodePacked(encodeLength(self.length, 128), self);
}
return encoded;
}
/**
* @dev RLP encodes a list of RLP encoded byte byte strings.
* @param self The list of RLP encoded byte strings.
* @return The RLP encoded list of items in bytes.
*/
function encodeList(bytes[] memory self)
internal
pure
returns (bytes memory)
{
bytes memory list = flatten(self);
return abi.encodePacked(encodeLength(list.length, 192), list);
}
/**
* @dev RLP encodes a list
* @param self concatenated bytes of RLP encoded bytes.
* @return The RLP encoded list of items in bytes
*/
function encodeList(bytes memory self)
internal
pure
returns (bytes memory)
{
return abi.encodePacked(encodeLength(self.length, 192), self);
}
/**
* @dev RLP encodes a string.
* @param self The string to encode.
* @return The RLP encoded string in bytes.
*/
function encodeString(string memory self)
internal
pure
returns (bytes memory)
{
return encodeBytes(bytes(self));
}
/**
* @dev RLP encodes an address.
* @param self The address to encode.
* @return The RLP encoded address in bytes.
*/
function encodeAddress(address self) internal pure returns (bytes memory) {
bytes memory inputBytes;
assembly {
let m := mload(0x40)
mstore(
add(m, 20),
xor(0x140000000000000000000000000000000000000000, self)
)
mstore(0x40, add(m, 52))
inputBytes := m
}
return encodeBytes(inputBytes);
}
/**
* @dev RLP encodes a uint.
* @param self The uint to encode.
* @return The RLP encoded uint in bytes.
*/
function encodeUint(uint256 self) internal pure returns (bytes memory) {
return encodeBytes(uintToBytes(self));
}
/**
* @dev RLP encodes an int.
* @param self The int to encode.
* @return The RLP encoded int in bytes.
*/
function encodeInt(int256 self) internal pure returns (bytes memory) {
return encodeBytes(intToBytes(self));
}
/**
* @dev RLP encodes a bool.
* @param self The bool to encode.
* @return The RLP encoded bool in bytes.
*/
function encodeBool(bool self) internal pure returns (bytes memory) {
bytes memory encoded = new bytes(1);
encoded[0] = (self ? bytes1(0x01) : bytes1(0x00));
return encoded;
}
/**
* @dev RLP encodes null.
* @return bytes for null
*/
function encodeNull() internal pure returns (bytes memory) {
return NULL;
}
/*
* Private functions
*/
/**
* @dev Encode the first byte, followed by the `len` in binary form if `length` is more than 55.
* @param len The length of the string or the payload.
* @param offset 128 if item is string, 192 if item is list.
* @return RLP encoded bytes.
*/
function encodeLength(uint256 len, uint256 offset)
private
pure
returns (bytes memory)
{
bytes memory encoded;
if (len < 56) {
encoded = new bytes(1);
encoded[0] = bytes32(len + offset)[31];
} else {
uint256 lenLen;
uint256 i = 1;
while (len / i != 0) {
lenLen++;
i *= 256;
}
encoded = new bytes(lenLen + 1);
encoded[0] = bytes32(lenLen + offset + 55)[31];
for (i = 1; i <= lenLen; i++) {
encoded[i] = bytes32((len / (256**(lenLen - i))) % 256)[31];
}
}
return encoded;
}
function lastBytesOf(int256 value, uint256 size) internal pure returns (bytes memory){
bytes memory buffer = new bytes(size);
assembly {
let dst := add(buffer, 32)
for { let idx := sub(32,size) } lt(idx,32) { idx := add(idx, 1) } {
mstore8(dst, byte(idx, value))
dst := add(dst, 1)
}
}
return buffer;
}
function intToBytes(int256 x) internal pure returns (bytes memory) {
if (x == 0) {
return new bytes(1);
}
int256 right = 0x80;
int256 left = -0x81;
for (uint i = 1 ; i<32 ; i++) {
if ((x<right) && (x>left)) {
return lastBytesOf(x, i);
}
right <<= 8;
left <<= 8;
}
return abi.encodePacked(x);
}
function uintToBytes(uint256 x) internal pure returns (bytes memory) {
if (x == 0) {
return new bytes(1);
}
uint256 right = 0x80;
for (uint i = 1 ; i<32 ; i++) {
if (x<right) {
return lastBytesOf(int256(x), i);
}
right <<= 8;
}
if (x<right) {
return abi.encodePacked(x);
} else {
return abi.encodePacked(bytes1(0), x);
}
}
/**
* @dev Flattens a list of byte strings into one byte string.
* @notice From: https://github.com/sammayo/solidity-rlp-encoder/blob/master/RLPEncode.sol.
* @param _list List of byte strings to flatten.
* @return The flattened byte string.
*/
function flatten(bytes[] memory _list) private pure returns (bytes memory) {
if (_list.length == 0) {
return new bytes(0);
}
uint256 len;
uint256 i;
for (i = 0; i < _list.length; i++) {
len += _list[i].length;
}
bytes memory flattened = new bytes(len);
uint256 flattenedPtr;
assembly {
flattenedPtr := add(flattened, 0x20)
}
for (i = 0; i < _list.length; i++) {
bytes memory item = _list[i];
uint256 listPtr;
assembly {
listPtr := add(item, 0x20)
}
memcpy(flattenedPtr, listPtr, item.length);
flattenedPtr += _list[i].length;
}
return flattened;
}
/**
* @dev Copies a piece of memory to another location.
* @notice From: https://github.com/Arachnid/solidity-stringutils/blob/master/src/strings.sol.
* @param dest Destination location.
* @param src Source location.
* @param len Length of memory to copy.
*/
function memcpy(uint dest, uint src, uint len) private pure {
// Copy word-length chunks while possible
for(; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
// Copy remaining bytes
uint mask = type(uint).max;
if (len > 0) {
mask = 256 ** (32 - len) - 1;
assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
/*
* Change supporting solidity compiler version
* The original code can be found via this link: https://github.com/hamdiallam/Solidity-RLP.git
*/
library RLPDecode {
uint8 private constant STRING_SHORT_START = 0x80;
uint8 private constant STRING_LONG_START = 0xb8;
uint8 private constant LIST_SHORT_START = 0xc0;
uint8 private constant LIST_LONG_START = 0xf8;
uint8 private constant WORD_SIZE = 32;
struct RLPItem {
uint256 len;
uint256 memPtr;
}
struct Iterator {
RLPItem item; // Item that's being iterated over.
uint256 nextPtr; // Position of the next item in the list.
}
/*
* @dev Returns the next element in the iteration. Reverts if it has not next element.
* @param self The iterator.
* @return The next element in the iteration.
*/
function next(Iterator memory self) internal pure returns (RLPItem memory) {
require(hasNext(self), "Must have next elements");
uint256 ptr = self.nextPtr;
uint256 itemLength = _itemLength(ptr);
self.nextPtr = ptr + itemLength;
return RLPItem(itemLength, ptr);
}
/*
* @dev Returns true if the iteration has more elements.
* @param self The iterator.
* @return true if the iteration has more elements.
*/
function hasNext(Iterator memory self) internal pure returns (bool) {
RLPItem memory item = self.item;
return self.nextPtr < item.memPtr + item.len;
}
/*
* @param item RLP encoded bytes
*/
function toRlpItem(bytes memory item)
internal
pure
returns (RLPItem memory)
{
uint256 memPtr;
assembly {
memPtr := add(item, 0x20)
}
return RLPItem(item.length, memPtr);
}
/*
* @dev Create an iterator. Reverts if item is not a list.
* @param self The RLP item.
* @return An 'Iterator' over the item.
*/
function iterator(RLPItem memory self)
internal
pure
returns (Iterator memory)
{
require(isList(self), "Must be a list");
uint256 ptr = self.memPtr + _payloadOffset(self.memPtr);
return Iterator(self, ptr);
}
/*
* @param item RLP encoded bytes
*/
function rlpLen(RLPItem memory item) internal pure returns (uint256) {
return item.len;
}
/*
* @param item RLP encoded bytes
*/
function payloadLen(RLPItem memory item) internal pure returns (uint256) {
return item.len - _payloadOffset(item.memPtr);
}
/*
* @param item RLP encoded list in bytes
*/
function toList(RLPItem memory item)
internal
pure
returns (RLPItem[] memory)
{
require(isList(item), "Must be a list");
uint256 items = numItems(item);
RLPItem[] memory result = new RLPItem[](items);
uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr);
uint256 dataLen;
for (uint256 i = 0; i < items; i++) {
dataLen = _itemLength(memPtr);
result[i] = RLPItem(dataLen, memPtr);
memPtr = memPtr + dataLen;
}
return result;
}
// @return indicator whether encoded payload is a list. negate this function call for isData.
function isList(RLPItem memory item) internal pure returns (bool) {
if (item.len == 0) return false;
uint8 byte0;
uint256 memPtr = item.memPtr;
assembly {
byte0 := byte(0, mload(memPtr))
}
if (byte0 < LIST_SHORT_START) return false;
return true;
}
function isNull(RLPItem memory item) internal pure returns (bool) {
if (item.len != 2) return false;
uint8 byte0;
uint8 itemLen;
uint256 memPtr = item.memPtr;
assembly {
byte0 := byte(0, mload(memPtr))
memPtr := add(memPtr, 1)
itemLen := byte(0, mload(memPtr))
}
if (byte0 != LIST_LONG_START || itemLen != 0) return false;
return true;
}
/** RLPItem conversions into data types **/
// @returns raw rlp encoding in bytes
function toRlpBytes(RLPItem memory item)
internal
pure
returns (bytes memory)
{
bytes memory result = new bytes(item.len);
if (result.length == 0) return result;
uint256 ptr;
assembly {
ptr := add(0x20, result)
}
copy(item.memPtr, ptr, item.len);
return result;
}
// any non-zero byte except "0x80" is considered true
function toBoolean(RLPItem memory item) internal pure returns (bool) {
require(item.len == 1, "Must have length 1");
uint256 result;
uint256 memPtr = item.memPtr;
assembly {
result := byte(0, mload(memPtr))
}
// SEE Github Issue #5.
// Summary: Most commonly used RLP libraries (i.e Geth) will encode
// "0" as "0x80" instead of as "0". We handle this edge case explicitly
// here.
if (result == 0 || result == STRING_SHORT_START) {
return false;
} else {
return true;
}
}
function toAddress(RLPItem memory item) internal pure returns (address) {
// 1 byte for the length prefix
require(item.len == 21, "Must have length 21");
return address(uint160(toUint(item)));
}
function toUint(RLPItem memory item) internal pure returns (uint256) {
require(item.len > 0 && item.len <= 33, "Invalid uint number");
uint256 offset = _payloadOffset(item.memPtr);
uint256 len = item.len - offset;
uint256 result;
uint256 memPtr = item.memPtr + offset;
assembly {
result := mload(memPtr)
// shfit to the correct location if neccesary
if lt(len, 32) {
result := div(result, exp(256, sub(32, len)))
}
}
return result;
}
function toInt(RLPItem memory item) internal pure returns (int256) {
require(item.len >= 0 && item.len < 33, "Invalid int number");
uint256 offset = _payloadOffset(item.memPtr);
uint256 len = item.len - offset;
int256 result;
uint256 memPtr = item.memPtr + offset;
assembly {
result := mload(memPtr)
if lt(len, 32) {
result := sar(mul(8, sub(32, len)), result)
}
}
return result;
}
// enforces 32 byte length
function toUintStrict(RLPItem memory item) internal pure returns (uint256) {
// one byte prefix
require(item.len == 33, "Must have length 33");
uint256 result;
uint256 memPtr = item.memPtr + 1;
assembly {
result := mload(memPtr)
}
return result;
}
function toBytes(RLPItem memory item) internal pure returns (bytes memory) {
require(item.len > 0, "Invalid length");
uint256 offset = _payloadOffset(item.memPtr);
uint256 len = item.len - offset; // data length
bytes memory result = new bytes(len);
uint256 destPtr;
assembly {
destPtr := add(0x20, result)
}
copy(item.memPtr + offset, destPtr, len);
return result;
}
/*
* Private Helpers
*/
// @return number of payload items inside an encoded list.
function numItems(RLPItem memory item) private pure returns (uint256) {
if (item.len == 0) return 0;
uint256 count = 0;
uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr);
uint256 endPtr = item.memPtr + item.len;
while (currPtr < endPtr) {
currPtr = currPtr + _itemLength(currPtr); // skip over an item
count++;
}
return count;
}
// @return entire rlp item byte length
function _itemLength(uint256 memPtr) private pure returns (uint256) {
uint256 itemLen;
uint256 byte0;
assembly {
byte0 := byte(0, mload(memPtr))
}
if (byte0 < STRING_SHORT_START) itemLen = 1;
else if (byte0 < STRING_LONG_START)
itemLen = byte0 - STRING_SHORT_START + 1;
else if (byte0 < LIST_SHORT_START) {
assembly {
let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is
memPtr := add(memPtr, 1) // skip over the first byte
/* 32 byte word size */
let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len
itemLen := add(dataLen, add(byteLen, 1))
}
} else if (byte0 < LIST_LONG_START) {
itemLen = byte0 - LIST_SHORT_START + 1;
} else {
assembly {
let byteLen := sub(byte0, 0xf7)
memPtr := add(memPtr, 1)
let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length
itemLen := add(dataLen, add(byteLen, 1))
}
}
return itemLen;
}
// @return number of bytes until the data
function _payloadOffset(uint256 memPtr) private pure returns (uint256) {
uint256 byte0;
assembly {
byte0 := byte(0, mload(memPtr))
}
if (byte0 < STRING_SHORT_START) return 0;
else if (
byte0 < STRING_LONG_START ||
(byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)
) return 1;
else if (byte0 < LIST_SHORT_START)
// being explicit
return byte0 - (STRING_LONG_START - 1) + 1;
else return byte0 - (LIST_LONG_START - 1) + 1;
}
/*
* @param src Pointer to source
* @param dest Pointer to destination
* @param len Amount of memory to copy from the source
*/
function copy(
uint256 src,
uint256 dest,
uint256 len
) private pure {
if (len == 0) return;
// copy as many word sizes as possible
for (; len >= WORD_SIZE; len -= WORD_SIZE) {
assembly {
mstore(dest, mload(src))
}
src += WORD_SIZE;
dest += WORD_SIZE;
}
if (len > 0) {
// left over bytes. Mask is used to remove unwanted bytes from the word
uint256 mask = 256**(WORD_SIZE - len) - 1;
assembly {
let srcpart := and(mload(src), not(mask)) // zero out src
let destpart := and(mload(dest), mask) // retrieve the bytes
mstore(dest, or(destpart, srcpart))
}
}
}
}{
"remappings": [
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@iconfoundation/xcall-solidity-library/=library/btp2/",
"@balanced/contracts/=src/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"NATIVE_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"_period","type":"uint256"},{"internalType":"uint256","name":"_percentage","type":"uint256"}],"name":"configureRateLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"currentLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"to","type":"string"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"to","type":"string"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositNative","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"to","type":"string"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"depositNative","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"to","type":"string"}],"name":"depositNative","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getWithdrawLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"from","type":"string"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"string[]","name":"protocols","type":"string[]"}],"name":"handleCallMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"iconAssetManager","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_xCall","type":"address"},{"internalType":"string","name":"_iconAssetManager","type":"string"},{"internalType":"address","name":"_xCallManager","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"percentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"resetLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"xCall","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xCallManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xCallNetworkAddress","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a06040523060805234801561001457600080fd5b50608051613d6c61003e60003960008181610f5a01528181610f8301526110c40152613d6c6000f3fe60806040526004361061019c5760003560e01c8063aaf10f42116100ec578063d4b19a1d1161008a578063d6f340a911610064578063d6f340a914610489578063e8bfdc53146104a9578063f2fde38b146104c9578063fc6308f7146104e957600080fd5b8063d4b19a1d14610427578063d4fb7e2d14610454578063d5bcb6101461047457600080fd5b8063b0434d21116100c6578063b0434d21146103a7578063bfe07da6146103c7578063cb03fb1e146103da578063ccc518041461040757600080fd5b8063aaf10f421461034c578063aba1fba614610361578063ad3cb1cc1461037657600080fd5b80635d6a16f511610159578063715018a611610133578063715018a6146102995780637bb7c0d8146102ae5780638da5cb5b146102ce578063a7b7b0871461031f57600080fd5b80635d6a16f514610253578063608fc37a146102735780636a7791dd1461028657600080fd5b80630a53d927146101a15780634096bf05146101e1578063456641411461020357806347e7ef24146102185780634f1ef2861461022b57806352d1902d1461023e575b600080fd5b3480156101ad57600080fd5b506101ce6101bc366004612f9c565b60076020526000908152604090205481565b6040519081526020015b60405180910390f35b3480156101ed57600080fd5b506101f66104fc565b6040516101d89190613007565b6102166102113660046130dd565b61058a565b005b61021661022636600461315a565b61059c565b610216610239366004613184565b6105ca565b34801561024a57600080fd5b506101ce6105e5565b34801561025f57600080fd5b5061021661026e366004613219565b610602565b6102166102813660046132e1565b610b13565b6102166102943660046132fa565b610b3f565b3480156102a557600080fd5b50610216610b4f565b3480156102ba57600080fd5b506102166102c9366004613366565b610b63565b3480156102da57600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03165b6040516001600160a01b0390911681526020016101d8565b34801561032b57600080fd5b506101ce61033a366004612f9c565b60056020526000908152604090205481565b34801561035857600080fd5b50610307610d25565b34801561036d57600080fd5b506101f6610d4b565b34801561038257600080fd5b506101f6604051806040016040528060058152602001640352e302e360dc1b81525081565b3480156103b357600080fd5b506102166103c23660046133c3565b610d58565b6102166103d53660046133f6565b610e40565b3480156103e657600080fd5b506101ce6103f5366004612f9c565b60066020526000908152604090205481565b34801561041357600080fd5b50610216610422366004612f9c565b610e5b565b34801561043357600080fd5b506101ce610442366004612f9c565b60046020526000908152604090205481565b34801561046057600080fd5b506101ce61046f366004612f9c565b610eb9565b34801561048057600080fd5b50610307600081565b34801561049557600080fd5b50600354610307906001600160a01b031681565b3480156104b557600080fd5b50600054610307906001600160a01b031681565b3480156104d557600080fd5b506102166104e4366004612f9c565b610ed8565b6102166104f7366004613442565b610f13565b6001805461050990613472565b80601f016020809104026020016040519081016040528092919081815260200182805461053590613472565b80156105825780601f1061055757610100808354040283529160200191610582565b820191906000526020600020905b81548152906001019060200180831161056557829003601f168201915b505050505081565b61059684848484610f2d565b50505050565b6105c682826040518060200160405280600081525060405180602001604052806000815250610f2d565b5050565b6105d2610f4f565b6105db82610ff4565b6105c68282610ffc565b60006105ef6110b9565b50600080516020613d1783398151915290565b6000546001600160a01b031633146106535760405162461bcd60e51b815260206004820152600f60248201526e6f6e6c7943616c6c5365727669636560881b60448201526064015b60405180910390fd5b6003546040516377ef816560e11b81526001600160a01b039091169063efdf02ca9061068590859085906004016134cf565b602060405180830381865afa1580156106a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c6919061356a565b6107065760405162461bcd60e51b81526020600482015260116024820152700a0e4dee8dec6ded8409ad2e6dac2e8c6d607b1b604482015260640161064a565b600061074785858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061110292505050565b905061077e6040518060400160405280600a8152602001695769746864726177546f60b01b8152508261116490919063ffffffff16565b1561095a576108506002805461079390613472565b80601f01602080910402602001604051908101604052809291908181526020018280546107bf90613472565b801561080c5780601f106107e15761010080835404028352916020019161080c565b820191906000526020600020905b8154815290600101906020018083116107ef57829003601f168201915b505050505088888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506111649050565b6108935760405162461bcd60e51b815260206004820152601460248201527337b7363ca4a1a7a720b9b9b2ba26b0b730b3b2b960611b604482015260640161064a565b60006108d486868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506111cb92505050565b60408051808201909152600f81526e125b9d985b1a59081858d8dbdd5b9d608a1b602082015281519192506109549161090c91611294565b61094a6040518060400160405280600f81526020016e125b9d985b1a59081858d8dbdd5b9d608a1b815250846020015161129490919063ffffffff16565b836040015161157a565b50610b0a565b60408051808201909152601081526f57697468647261774e6174697665546f60801b602082015261098c908290611164565b156109ef5760405162461bcd60e51b815260206004820152602d60248201527f576974686472617720746f206e61746976652069732063757272656e746c792060448201526c1b9bdd081cdd5c1c1bdc9d1959609a1b606482015260840161064a565b60408051808201909152600d81526c11195c1bdcda5d14995d995c9d609a1b6020820152610a1e908290611164565b15610acb57610a336001805461079390613472565b610a715760405162461bcd60e51b815260206004820152600f60248201526e6f6e6c7943616c6c5365727669636560881b604482015260640161064a565b6000610ab286868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061166492505050565b905061095481600001518260400151836020015161157a565b60405162461bcd60e51b8152602060048201526014602482015273556e6b6e6f776e206d657373616765207479706560601b604482015260640161064a565b50505050505050565b610b3c81604051806020016040528060008152506040518060200160405280600081525061172f565b50565b610b4a83838361172f565b505050565b610b5761179b565b610b6160006117f6565b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b0316600081158015610ba85750825b90506000826001600160401b03166001148015610bc45750303b155b905081158015610bd2575080155b15610bf05760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610c1a57845460ff60401b1916600160401b1785555b600080546001600160a01b0319166001600160a01b038a16908117825560408051636bf459cb60e01b815290519192636bf459cb926004808401938290030181865afa158015610c6e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c9691908101906135d1565b600190610ca39082613653565b506002610cb08882613653565b50600380546001600160a01b0319166001600160a01b038816179055610cd533611867565b8315610d1b57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b6000610d46600080516020613d17833981519152546001600160a01b031690565b905090565b6002805461050990613472565b610d6061179b565b612710811115610dcc5760405162461bcd60e51b815260206004820152603160248201527f50657263656e746167652073686f756c64206265206c657373207468616e206f6044820152707220657175616c20746f20504f494e545360781b606482015260840161064a565b6001600160a01b0383166000908152600460209081526040808320859055600582528083208490556006909152902042905561271081610e0b85611878565b610e159190613728565b610e1f9190613755565b6001600160a01b039093166000908152600760205260409020929092555050565b610b4a83838360405180602001604052806000815250610f2d565b610e6361179b565b6001600160a01b03811660009081526005602052604090205461271090610e8983611878565b610e939190613728565b610e9d9190613755565b6001600160a01b03909116600090815260076020526040902055565b600080610ec583611878565b9050610ed181846118f7565b9392505050565b610ee061179b565b6001600160a01b038116610f0a57604051631e4fbdf760e01b81526000600482015260240161064a565b610b3c816117f6565b6105c682826040518060200160405280600081525061172f565b610f426001600160a01b0385163330866119ee565b6105968484848434611a55565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480610fd657507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610fca600080516020613d17833981519152546001600160a01b031690565b6001600160a01b031614155b15610b615760405163703e46dd60e11b815260040160405180910390fd5b610b3c61179b565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611056575060408051601f3d908101601f1916820190925261105391810190613769565b60015b61107e57604051634c9c8ce360e01b81526001600160a01b038316600482015260240161064a565b600080516020613d1783398151915281146110af57604051632a87526960e21b81526004810182905260240161064a565b610b4a8383611bea565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b615760405163703e46dd60e11b815260040160405180910390fd5b6060600061113f61113a8460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b611c40565b9050610ed18160008151811061115757611157613782565b6020026020010151611d89565b6000816040516020016111779190613798565b604051602081830303815290604052805190602001208360405160200161119e9190613798565b60405160208183030381529060405280519060200120036111c1575060016111c5565b5060005b92915050565b6111ef60405180606001604052806060815260200160608152602001600081525090565b600061122561113a8460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b905060405180606001604052806112488360018151811061115757611157613782565b81526020016112638360028151811061115757611157613782565b815260200161128b8360038151811061127e5761127e613782565b6020026020010151611e62565b90529392505050565b81516000908390602a1480156112d85750600360fc1b6001600160f81b031916816000815181106112c7576112c7613782565b01602001516001600160f81b031916145b80156113125750600f60fb1b6001600160f81b0319168160018151811061130157611301613782565b01602001516001600160f81b031916145b83906113315760405162461bcd60e51b815260040161064a9190613007565b5060408051601480825281830190925260009160208201818036833701905050905060008080805b60288110156114cb578561136e8260026137b4565b8151811061137e5761137e613782565b016020015160f81c935060016030851015611397575060005b8460ff1660391080156113ad575060418560ff16105b156113b6575060005b8460ff1660461080156113cc575060618560ff16105b156113d5575060005b8460ff16606610156113e5575060005b80611404578860405162461bcd60e51b815260040161064a9190613007565b60418560ff1610156114195760309250611433565b8460ff166046101561142e5760579250611433565b603792505b61143e6002836137c7565b6000036114565761144f83866137db565b93506114b8565b61146083866137db565b61146b8560106137f4565b6114759190613810565b60f81b866002611486600186613829565b6114909190613755565b815181106114a0576114a0613782565b60200101906001600160f81b031916908160001a9053505b50806114c38161383c565b915050611359565b506000846040516020016114df9190613798565b60408051601f198184030181529190526014810151975090506001600160a01b03871661156e5760025b865181101561156c5786818151811061152457611524613782565b60209101015189906001600160f81b031916600360fc1b146115595760405162461bcd60e51b815260040161064a9190613007565b50806115648161383c565b915050611509565b505b50505050505092915050565b600081116115ca5760405162461bcd60e51b815260206004820152601f60248201527f416d6f756e74206c657373207468616e206d696e696d756d20616d6f756e7400604482015260640161064a565b6115d48382611f14565b6001600160a01b038316611650576040516000906001600160a01b0384169083156108fc0290849084818181858888f193505050509050806105965760405162461bcd60e51b81526020600482015260156024820152744661696c656420746f2073656e6420746f6b656e7360581b604482015260640161064a565b610b4a6001600160a01b0384168383611fb0565b60408051606081018252600080825260208083018290528284018290528351808501855282815281018290528351808501909452845184528481019084015290916116ae90611c40565b905060405180606001604052806116de836001815181106116d1576116d1613782565b6020026020010151611fe1565b6001600160a01b031681526020016117028360028151811061127e5761127e613782565b815260200161171d836003815181106116d1576116d1613782565b6001600160a01b031690529392505050565b8234101561177f5760405162461bcd60e51b815260206004820152601f60248201527f416d6f756e74206c657373207468616e206d696e696d756d20616d6f756e7400604482015260640161064a565b600061178b8434613829565b9050610596600085858585611a55565b336117cd7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610b615760405163118cdaa760e01b815233600482015260240161064a565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b61186f612034565b610b3c8161207d565b60006001600160a01b03821661188f575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156118d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c59190613769565b6001600160a01b038116600090815260046020908152604080832054600590925282205481830361192d576000925050506111c5565b600061271061193c8388613728565b6119469190613755565b905060006119548288613829565b6001600160a01b0387166000908152600660205260408120549192509061197b9042613829565b90506119878186612085565b90506000856119968385613728565b6119a09190613755565b6001600160a01b038916600090815260076020526040812054919250906119c8908390613829565b90506119d48a82612085565b90506119e0818661209b565b9a9950505050505050505050565b6040516001600160a01b0384811660248301528381166044830152606482018390526105969186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506120aa565b60006040518060a00160405280611a74886001600160a01b031661210d565b8152602001611a823361210d565b815260200185815260200186815260200184815250905060006040518060600160405280886001600160a01b03168152602001878152602001336001600160a01b031681525090506000600360009054906101000a90046001600160a01b03166001600160a01b031663f434bb686040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b1f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b4791908101906138f3565b6000549091506001600160a01b031663edc6afff856002611b6787612118565b611b70876121b2565b865160208801516040516001600160e01b031960e089901b168152611b9c9594939291906004016139e1565b60206040518083038185885af1158015611bba573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611bdf9190613769565b505050505050505050565b611bf38261222e565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115611c3857610b4a8282612293565b6105c6612309565b6060611c4b82612328565b611c885760405162461bcd60e51b815260206004820152600e60248201526d135d5cdd0818994818481b1a5cdd60921b604482015260640161064a565b6000611c9383612363565b90506000816001600160401b03811115611caf57611caf61301a565b604051908082528060200260200182016040528015611cf457816020015b6040805180820190915260008082526020820152815260200190600190039081611ccd5790505b5090506000611d0685602001516123e8565b8560200151611d1591906137b4565b90506000805b84811015611d7e57611d2c83612469565b9150604051806040016040528083815260200184815250848281518110611d5557611d55613782565b6020908102919091010152611d6a82846137b4565b925080611d768161383c565b915050611d1b565b509195945050505050565b8051606090611dcb5760405162461bcd60e51b815260206004820152600e60248201526d092dcecc2d8d2c840d8cadccee8d60931b604482015260640161064a565b6000611dda83602001516123e8565b90506000818460000151611dee9190613829565b90506000816001600160401b03811115611e0a57611e0a61301a565b6040519080825280601f01601f191660200182016040528015611e34576020820181803683370190505b5090506000816020019050611e59848760200151611e5291906137b4565b8285612512565b50949350505050565b805160009015801590611e7757508151602110155b611eb95760405162461bcd60e51b815260206004820152601360248201527224b73b30b634b2103ab4b73a10373ab6b132b960691b604482015260640161064a565b6000611ec883602001516123e8565b90506000818460000151611edc9190613829565b9050600080838660200151611ef191906137b4565b9050805191506020831015611e5957506020919091036101000a90049392505050565b6000611f1f83611878565b90506000611f2d82856118f7565b905080611f3a8484613829565b1015611f815760405162461bcd60e51b8152602060048201526016602482015275195e18d959591cc81dda5d1a191c985dc81b1a5b5a5d60521b604482015260640161064a565b6001600160a01b0390931660009081526007602090815260408083209590955560069052929092204290555050565b6040516001600160a01b03838116602483015260448201839052610b4a91859182169063a9059cbb90606401611a23565b805160009060151461202b5760405162461bcd60e51b81526020600482015260136024820152724d7573742068617665206c656e67746820323160681b604482015260640161064a565b6111c582611e62565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610b6157604051631afcd79f60e31b815260040160405180910390fd5b610ee0612034565b60008183106120945781610ed1565b5090919050565b60008183116120945781610ed1565b60006120bf6001600160a01b03841683612594565b905080516000141580156120e45750808060200190518101906120e2919061356a565b155b15610b4a57604051635274afe760e01b81526001600160a01b038416600482015260240161064a565b60606111c5826125a2565b606060006121446040518060400160405280600781526020016611195c1bdcda5d60ca1b815250612777565b835161214f90612777565b61215c8560200151612777565b6121698660400151612777565b6121768760600151612782565b6121838860800151612790565b60405160200161219896959493929190613ab3565b6040516020818303038152906040529050610ed1816127ff565b606060006121e46040518060400160405280600d81526020016c11195c1bdcda5d14995d995c9d609a1b815250612777565b83516121f8906001600160a01b0316612835565b6122058560200151612782565b61221b86604001516001600160a01b0316612835565b6040516020016121989493929190613b32565b806001600160a01b03163b60000361226457604051634c9c8ce360e01b81526001600160a01b038216600482015260240161064a565b600080516020613d1783398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516122b09190613798565b600060405180830381855af49150503d80600081146122eb576040519150601f19603f3d011682016040523d82523d6000602084013e6122f0565b606091505b5091509150612300858383612858565b95945050505050565b3415610b615760405163b398979f60e01b815260040160405180910390fd5b8051600090810361233b57506000919050565b6020820151805160001a9060c0821015612359575060009392505050565b5060019392505050565b8051600090810361237657506000919050565b60008061238684602001516123e8565b846020015161239591906137b4565b90506000846000015185602001516123ad91906137b4565b90505b808210156123df576123c182612469565b6123cb90836137b4565b9150826123d78161383c565b9350506123b0565b50909392505050565b8051600090811a60808110156124015750600092915050565b60b881108061241c575060c0811080159061241c575060f881105b1561242a5750600192915050565b60c08110156124575761243f600160b86137db565b61244c9060ff1682613829565b610ed19060016137b4565b61243f600160f86137db565b50919050565b80516000908190811a6080811015612484576001915061250b565b60b88110156124aa57612498608082613829565b6124a39060016137b4565b915061250b565b60c08110156124d75760b78103600185019450806020036101000a8551046001820181019350505061250b565b60f88110156124eb5761249860c082613829565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b8060000361251f57505050565b6020811061255757825182526125366020846137b4565b92506125436020836137b4565b9150612550602082613829565b905061251f565b8015610b4a576000600161256c836020613829565b61257890610100613c6d565b6125829190613829565b84518451821691191617835250505050565b6060610ed1838360006128ad565b604080516028808252606082810190935283831b9160009160208201818036833701905050905060008060008060008060006125dd8b61294a565b905060005b6014811015612746576125f6816013613829565b612601906008613728565b61260c906002613c6d565b61261a9060608c901c613755565b9750612627601089613c79565b96506126348760106137f4565b61263e90896137db565b95508161264c826002613728565b6028811061265c5761265c613782565b602002015194508161266f826002613728565b61267a9060016137b4565b6028811061268a5761268a613782565b6020020151935061269b8786612adb565b92506126a78388613810565b60f81b896126b6836002613728565b815181106126c6576126c6613782565b60200101906001600160f81b031916908160001a9053506126e78685612adb565b92506126f38387613810565b60f81b89612702836002613728565b61270d9060016137b4565b8151811061271d5761271d613782565b60200101906001600160f81b031916908160001a9053508061273e8161383c565b9150506125e2565b50876040516020016127589190613c9b565b6040516020818303038152906040529950505050505050505050919050565b60606111c582612790565b60606111c561279083612b08565b606080825160011480156127be57506080836000815181106127b4576127b4613782565b016020015160f81c105b156127ca5750816111c5565b6127d683516080612bbc565b836040516020016127e8929190613cc5565b604051602081830303815290604052905092915050565b606061280d825160c0612bbc565b8260405160200161281f929190613cc5565b6040516020818303038152906040529050919050565b60408051600560a21b8318601482015260348101909152606090610ed181612790565b60608261286d5761286882612d72565b610ed1565b815115801561288457506001600160a01b0384163b155b1561250b57604051639996b31560e01b81526001600160a01b038516600482015260240161064a565b6060814710156128d25760405163cd78605960e01b815230600482015260240161064a565b600080856001600160a01b031684866040516128ee9190613798565b60006040518083038185875af1925050503d806000811461292b576040519150601f19603f3d011682016040523d82523d6000602084013e612930565b606091505b5091509150612940868383612858565b9695505050505050565b612952612f61565b606082901b600061296282612d9b565b6040516020016129729190613798565b60405160208183030381529060405280519060200120905060008060008060005b6014811015612acf5760108782601481106129b0576129b0613782565b6129bc9291901a613cf4565b93506010848883601481106129d3576129d3613782565b6129df9291901a6137db565b6129e99190613c79565b945060108682602081106129ff576129ff613782565b612a0b9291901a613cf4565b9150601082878360208110612a2257612a22613782565b612a2e9291901a6137db565b612a389190613c79565b925060098560ff16118015612a50575060078360ff16115b88612a5c836002613728565b60288110612a6c57612a6c613782565b91151560209092020152600960ff8516118015612a8c575060078260ff16115b88612a98836002613728565b612aa39060016137b4565b60288110612ab357612ab3613782565b9115156020909202015280612ac78161383c565b915050612993565b50505050505050919050565b6000600a8360ff161015612af1575060306111c5565b8115612aff575060376111c5565b50605792915050565b606081600003612b3557604080516001808252818301909252906020820181803683370190505092915050565b608060015b6020811015612b765781841015612b5d57612b558482612ef5565b949350505050565b60089190911b9080612b6e8161383c565b915050612b3a565b5080831015612ba3576040805160208101859052015b604051602081830303815290604052915050919050565b6040516000602082015260218101849052604101612b8c565b6060806038841015612c265760408051600180825281830190925290602082018180368337019050509050612bf183856137b4565b601f1a60f81b81600081518110612c0a57612c0a613782565b60200101906001600160f81b031916908160001a905350610ed1565b600060015b612c358187613755565b15612c5b5781612c448161383c565b9250612c54905061010082613728565b9050612c2b565b612c668260016137b4565b6001600160401b03811115612c7d57612c7d61301a565b6040519080825280601f01601f191660200182016040528015612ca7576020820181803683370190505b509250612cb485836137b4565b612cbf9060376137b4565b601f1a60f81b83600081518110612cd857612cd8613782565b60200101906001600160f81b031916908160001a905350600190505b818111612d6957610100612d088284613829565b612d1490610100613c6d565b612d1e9088613755565b612d2891906137c7565b601f1a60f81b838281518110612d4057612d40613782565b60200101906001600160f81b031916908160001a90535080612d618161383c565b915050612cf4565b50509392505050565b805115612d825780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60408051602880825260608281019093526000919060208201818036833701905050905060008080805b6014811015612eea57612dd9816013613829565b612de4906008613728565b612def906002613c6d565b612dfd90606089901c613755565b9350612e0a601085613c79565b9250612e178360106137f4565b612e2190856137db565b9150600a8360ff1610612e35576057612e38565b60305b612e429084613810565b60f81b85612e51836002613728565b81518110612e6157612e61613782565b60200101906001600160f81b031916908160001a905350600a8260ff1610612e8a576057612e8d565b60305b612e979083613810565b60f81b85612ea6836002613728565b612eb19060016137b4565b81518110612ec157612ec1613782565b60200101906001600160f81b031916908160001a90535080612ee28161383c565b915050612dc5565b509295945050505050565b60606000826001600160401b03811115612f1157612f1161301a565b6040519080825280601f01601f191660200182016040528015612f3b576020820181803683370190505b50905060208101836020035b6020811015612d695785811a825360019182019101612f47565b6040518061050001604052806028906020820280368337509192915050565b80356001600160a01b0381168114612f9757600080fd5b919050565b600060208284031215612fae57600080fd5b610ed182612f80565b60005b83811015612fd2578181015183820152602001612fba565b50506000910152565b60008151808452612ff3816020860160208601612fb7565b601f01601f19169290920160200192915050565b602081526000610ed16020830184612fdb565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156130585761305861301a565b604052919050565b60006001600160401b038211156130795761307961301a565b50601f01601f191660200190565b600082601f83011261309857600080fd5b81356130ab6130a682613060565b613030565b8181528460208386010111156130c057600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156130f357600080fd5b6130fc85612f80565b93506020850135925060408501356001600160401b038082111561311f57600080fd5b61312b88838901613087565b9350606087013591508082111561314157600080fd5b5061314e87828801613087565b91505092959194509250565b6000806040838503121561316d57600080fd5b61317683612f80565b946020939093013593505050565b6000806040838503121561319757600080fd5b6131a083612f80565b915060208301356001600160401b038111156131bb57600080fd5b6131c785828601613087565b9150509250929050565b60008083601f8401126131e357600080fd5b5081356001600160401b038111156131fa57600080fd5b60208301915083602082850101111561321257600080fd5b9250929050565b6000806000806000806060878903121561323257600080fd5b86356001600160401b038082111561324957600080fd5b6132558a838b016131d1565b9098509650602089013591508082111561326e57600080fd5b61327a8a838b016131d1565b9096509450604089013591508082111561329357600080fd5b818901915089601f8301126132a757600080fd5b8135818111156132b657600080fd5b8a60208260051b85010111156132cb57600080fd5b6020830194508093505050509295509295509295565b6000602082840312156132f357600080fd5b5035919050565b60008060006060848603121561330f57600080fd5b8335925060208401356001600160401b038082111561332d57600080fd5b61333987838801613087565b9350604086013591508082111561334f57600080fd5b5061335c86828701613087565b9150509250925092565b60008060006060848603121561337b57600080fd5b61338484612f80565b925060208401356001600160401b0381111561339f57600080fd5b6133ab86828701613087565b9250506133ba60408501612f80565b90509250925092565b6000806000606084860312156133d857600080fd5b6133e184612f80565b95602085013595506040909401359392505050565b60008060006060848603121561340b57600080fd5b61341484612f80565b92506020840135915060408401356001600160401b0381111561343657600080fd5b61335c86828701613087565b6000806040838503121561345557600080fd5b8235915060208301356001600160401b038111156131bb57600080fd5b600181811c9082168061348657607f821691505b60208210810361246357634e487b7160e01b600052602260045260246000fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208082528181018390526000906040600585901b8401810190840186845b8781101561355d57868403603f190183528135368a9003601e1901811261351457600080fd5b890185810190356001600160401b0381111561352f57600080fd5b80360382131561353e57600080fd5b6135498682846134a6565b9550505091840191908401906001016134ee565b5091979650505050505050565b60006020828403121561357c57600080fd5b81518015158114610ed157600080fd5b600082601f83011261359d57600080fd5b81516135ab6130a682613060565b8181528460208386010111156135c057600080fd5b612b55826020830160208701612fb7565b6000602082840312156135e357600080fd5b81516001600160401b038111156135f957600080fd5b612b558482850161358c565b601f821115610b4a57600081815260208120601f850160051c8101602086101561362c5750805b601f850160051c820191505b8181101561364b57828155600101613638565b505050505050565b81516001600160401b0381111561366c5761366c61301a565b6136808161367a8454613472565b84613605565b602080601f8311600181146136b5576000841561369d5750858301515b600019600386901b1c1916600185901b17855561364b565b600085815260208120601f198616915b828110156136e4578886015182559484019460019091019084016136c5565b50858210156137025787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176111c5576111c5613712565b634e487b7160e01b600052601260045260246000fd5b6000826137645761376461373f565b500490565b60006020828403121561377b57600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600082516137aa818460208701612fb7565b9190910192915050565b808201808211156111c5576111c5613712565b6000826137d6576137d661373f565b500690565b60ff82811682821603908111156111c5576111c5613712565b60ff818116838216029081169081811461250b5761250b613712565b60ff81811683821601908111156111c5576111c5613712565b818103818111156111c5576111c5613712565b60006001820161384e5761384e613712565b5060010190565b600082601f83011261386657600080fd5b815160206001600160401b03808311156138825761388261301a565b8260051b613891838201613030565b93845285810183019383810190888611156138ab57600080fd5b84880192505b858310156138e7578251848111156138c95760008081fd5b6138d78a87838c010161358c565b83525091840191908401906138b1565b98975050505050505050565b60006020828403121561390557600080fd5b81516001600160401b038082111561391c57600080fd5b908301906040828603121561393057600080fd5b60405160408101818110838211171561394b5761394b61301a565b60405282518281111561395d57600080fd5b61396987828601613855565b82525060208301518281111561397e57600080fd5b61398a87828601613855565b60208301525095945050505050565b600081518084526020808501808196508360051b8101915082860160005b8581101561355d5782840389526139cf848351612fdb565b988501989350908401906001016139b7565b60a0815260008087546139f381613472565b8060a086015260c0600180841660008114613a155760018114613a2f57613a60565b60ff1985168884015283151560051b880183019550613a60565b8c60005260208060002060005b86811015613a575781548b8201870152908401908201613a3c565b8a018501975050505b50505050508281036020840152613a778188612fdb565b90508281036040840152613a8b8187612fdb565b90508281036060840152613a9f8186613999565b905082810360808401526138e78185613999565b600087516020613ac68285838d01612fb7565b885191840191613ad98184848d01612fb7565b8851920191613aeb8184848c01612fb7565b8751920191613afd8184848b01612fb7565b8651920191613b0f8184848a01612fb7565b8551920191613b218184848901612fb7565b919091019998505050505050505050565b60008551613b44818460208a01612fb7565b855190830190613b58818360208a01612fb7565b8551910190613b6b818360208901612fb7565b8451910190613b7e818360208801612fb7565b019695505050505050565b600181815b80851115613bc4578160001904821115613baa57613baa613712565b80851615613bb757918102915b93841c9390800290613b8e565b509250929050565b600082613bdb575060016111c5565b81613be8575060006111c5565b8160018114613bfe5760028114613c0857613c24565b60019150506111c5565b60ff841115613c1957613c19613712565b50506001821b6111c5565b5060208310610133831016604e8410600b8410161715613c47575081810a6111c5565b613c518383613b89565b8060001904821115613c6557613c65613712565b029392505050565b6000610ed18383613bcc565b600060ff831680613c8c57613c8c61373f565b8060ff84160491505092915050565b61060f60f31b815260008251613cb8816002850160208701612fb7565b9190910160020192915050565b60008351613cd7818460208801612fb7565b835190830190613ceb818360208801612fb7565b01949350505050565b600060ff831680613d0757613d0761373f565b8060ff8416069150509291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca264697066735822122016355eb5cd96b06d4f2dbf0184d802f3eab8eeec53bf3f1a9092370c22523d3064736f6c63430008150033
Deployed Bytecode
0x60806040526004361061019c5760003560e01c8063aaf10f42116100ec578063d4b19a1d1161008a578063d6f340a911610064578063d6f340a914610489578063e8bfdc53146104a9578063f2fde38b146104c9578063fc6308f7146104e957600080fd5b8063d4b19a1d14610427578063d4fb7e2d14610454578063d5bcb6101461047457600080fd5b8063b0434d21116100c6578063b0434d21146103a7578063bfe07da6146103c7578063cb03fb1e146103da578063ccc518041461040757600080fd5b8063aaf10f421461034c578063aba1fba614610361578063ad3cb1cc1461037657600080fd5b80635d6a16f511610159578063715018a611610133578063715018a6146102995780637bb7c0d8146102ae5780638da5cb5b146102ce578063a7b7b0871461031f57600080fd5b80635d6a16f514610253578063608fc37a146102735780636a7791dd1461028657600080fd5b80630a53d927146101a15780634096bf05146101e1578063456641411461020357806347e7ef24146102185780634f1ef2861461022b57806352d1902d1461023e575b600080fd5b3480156101ad57600080fd5b506101ce6101bc366004612f9c565b60076020526000908152604090205481565b6040519081526020015b60405180910390f35b3480156101ed57600080fd5b506101f66104fc565b6040516101d89190613007565b6102166102113660046130dd565b61058a565b005b61021661022636600461315a565b61059c565b610216610239366004613184565b6105ca565b34801561024a57600080fd5b506101ce6105e5565b34801561025f57600080fd5b5061021661026e366004613219565b610602565b6102166102813660046132e1565b610b13565b6102166102943660046132fa565b610b3f565b3480156102a557600080fd5b50610216610b4f565b3480156102ba57600080fd5b506102166102c9366004613366565b610b63565b3480156102da57600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03165b6040516001600160a01b0390911681526020016101d8565b34801561032b57600080fd5b506101ce61033a366004612f9c565b60056020526000908152604090205481565b34801561035857600080fd5b50610307610d25565b34801561036d57600080fd5b506101f6610d4b565b34801561038257600080fd5b506101f6604051806040016040528060058152602001640352e302e360dc1b81525081565b3480156103b357600080fd5b506102166103c23660046133c3565b610d58565b6102166103d53660046133f6565b610e40565b3480156103e657600080fd5b506101ce6103f5366004612f9c565b60066020526000908152604090205481565b34801561041357600080fd5b50610216610422366004612f9c565b610e5b565b34801561043357600080fd5b506101ce610442366004612f9c565b60046020526000908152604090205481565b34801561046057600080fd5b506101ce61046f366004612f9c565b610eb9565b34801561048057600080fd5b50610307600081565b34801561049557600080fd5b50600354610307906001600160a01b031681565b3480156104b557600080fd5b50600054610307906001600160a01b031681565b3480156104d557600080fd5b506102166104e4366004612f9c565b610ed8565b6102166104f7366004613442565b610f13565b6001805461050990613472565b80601f016020809104026020016040519081016040528092919081815260200182805461053590613472565b80156105825780601f1061055757610100808354040283529160200191610582565b820191906000526020600020905b81548152906001019060200180831161056557829003601f168201915b505050505081565b61059684848484610f2d565b50505050565b6105c682826040518060200160405280600081525060405180602001604052806000815250610f2d565b5050565b6105d2610f4f565b6105db82610ff4565b6105c68282610ffc565b60006105ef6110b9565b50600080516020613d1783398151915290565b6000546001600160a01b031633146106535760405162461bcd60e51b815260206004820152600f60248201526e6f6e6c7943616c6c5365727669636560881b60448201526064015b60405180910390fd5b6003546040516377ef816560e11b81526001600160a01b039091169063efdf02ca9061068590859085906004016134cf565b602060405180830381865afa1580156106a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c6919061356a565b6107065760405162461bcd60e51b81526020600482015260116024820152700a0e4dee8dec6ded8409ad2e6dac2e8c6d607b1b604482015260640161064a565b600061074785858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061110292505050565b905061077e6040518060400160405280600a8152602001695769746864726177546f60b01b8152508261116490919063ffffffff16565b1561095a576108506002805461079390613472565b80601f01602080910402602001604051908101604052809291908181526020018280546107bf90613472565b801561080c5780601f106107e15761010080835404028352916020019161080c565b820191906000526020600020905b8154815290600101906020018083116107ef57829003601f168201915b505050505088888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506111649050565b6108935760405162461bcd60e51b815260206004820152601460248201527337b7363ca4a1a7a720b9b9b2ba26b0b730b3b2b960611b604482015260640161064a565b60006108d486868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506111cb92505050565b60408051808201909152600f81526e125b9d985b1a59081858d8dbdd5b9d608a1b602082015281519192506109549161090c91611294565b61094a6040518060400160405280600f81526020016e125b9d985b1a59081858d8dbdd5b9d608a1b815250846020015161129490919063ffffffff16565b836040015161157a565b50610b0a565b60408051808201909152601081526f57697468647261774e6174697665546f60801b602082015261098c908290611164565b156109ef5760405162461bcd60e51b815260206004820152602d60248201527f576974686472617720746f206e61746976652069732063757272656e746c792060448201526c1b9bdd081cdd5c1c1bdc9d1959609a1b606482015260840161064a565b60408051808201909152600d81526c11195c1bdcda5d14995d995c9d609a1b6020820152610a1e908290611164565b15610acb57610a336001805461079390613472565b610a715760405162461bcd60e51b815260206004820152600f60248201526e6f6e6c7943616c6c5365727669636560881b604482015260640161064a565b6000610ab286868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061166492505050565b905061095481600001518260400151836020015161157a565b60405162461bcd60e51b8152602060048201526014602482015273556e6b6e6f776e206d657373616765207479706560601b604482015260640161064a565b50505050505050565b610b3c81604051806020016040528060008152506040518060200160405280600081525061172f565b50565b610b4a83838361172f565b505050565b610b5761179b565b610b6160006117f6565b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b0316600081158015610ba85750825b90506000826001600160401b03166001148015610bc45750303b155b905081158015610bd2575080155b15610bf05760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610c1a57845460ff60401b1916600160401b1785555b600080546001600160a01b0319166001600160a01b038a16908117825560408051636bf459cb60e01b815290519192636bf459cb926004808401938290030181865afa158015610c6e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c9691908101906135d1565b600190610ca39082613653565b506002610cb08882613653565b50600380546001600160a01b0319166001600160a01b038816179055610cd533611867565b8315610d1b57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b6000610d46600080516020613d17833981519152546001600160a01b031690565b905090565b6002805461050990613472565b610d6061179b565b612710811115610dcc5760405162461bcd60e51b815260206004820152603160248201527f50657263656e746167652073686f756c64206265206c657373207468616e206f6044820152707220657175616c20746f20504f494e545360781b606482015260840161064a565b6001600160a01b0383166000908152600460209081526040808320859055600582528083208490556006909152902042905561271081610e0b85611878565b610e159190613728565b610e1f9190613755565b6001600160a01b039093166000908152600760205260409020929092555050565b610b4a83838360405180602001604052806000815250610f2d565b610e6361179b565b6001600160a01b03811660009081526005602052604090205461271090610e8983611878565b610e939190613728565b610e9d9190613755565b6001600160a01b03909116600090815260076020526040902055565b600080610ec583611878565b9050610ed181846118f7565b9392505050565b610ee061179b565b6001600160a01b038116610f0a57604051631e4fbdf760e01b81526000600482015260240161064a565b610b3c816117f6565b6105c682826040518060200160405280600081525061172f565b610f426001600160a01b0385163330866119ee565b6105968484848434611a55565b306001600160a01b037f000000000000000000000000f560fca8295d305db78853b93a414375889ede0f161480610fd657507f000000000000000000000000f560fca8295d305db78853b93a414375889ede0f6001600160a01b0316610fca600080516020613d17833981519152546001600160a01b031690565b6001600160a01b031614155b15610b615760405163703e46dd60e11b815260040160405180910390fd5b610b3c61179b565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611056575060408051601f3d908101601f1916820190925261105391810190613769565b60015b61107e57604051634c9c8ce360e01b81526001600160a01b038316600482015260240161064a565b600080516020613d1783398151915281146110af57604051632a87526960e21b81526004810182905260240161064a565b610b4a8383611bea565b306001600160a01b037f000000000000000000000000f560fca8295d305db78853b93a414375889ede0f1614610b615760405163703e46dd60e11b815260040160405180910390fd5b6060600061113f61113a8460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b611c40565b9050610ed18160008151811061115757611157613782565b6020026020010151611d89565b6000816040516020016111779190613798565b604051602081830303815290604052805190602001208360405160200161119e9190613798565b60405160208183030381529060405280519060200120036111c1575060016111c5565b5060005b92915050565b6111ef60405180606001604052806060815260200160608152602001600081525090565b600061122561113a8460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b905060405180606001604052806112488360018151811061115757611157613782565b81526020016112638360028151811061115757611157613782565b815260200161128b8360038151811061127e5761127e613782565b6020026020010151611e62565b90529392505050565b81516000908390602a1480156112d85750600360fc1b6001600160f81b031916816000815181106112c7576112c7613782565b01602001516001600160f81b031916145b80156113125750600f60fb1b6001600160f81b0319168160018151811061130157611301613782565b01602001516001600160f81b031916145b83906113315760405162461bcd60e51b815260040161064a9190613007565b5060408051601480825281830190925260009160208201818036833701905050905060008080805b60288110156114cb578561136e8260026137b4565b8151811061137e5761137e613782565b016020015160f81c935060016030851015611397575060005b8460ff1660391080156113ad575060418560ff16105b156113b6575060005b8460ff1660461080156113cc575060618560ff16105b156113d5575060005b8460ff16606610156113e5575060005b80611404578860405162461bcd60e51b815260040161064a9190613007565b60418560ff1610156114195760309250611433565b8460ff166046101561142e5760579250611433565b603792505b61143e6002836137c7565b6000036114565761144f83866137db565b93506114b8565b61146083866137db565b61146b8560106137f4565b6114759190613810565b60f81b866002611486600186613829565b6114909190613755565b815181106114a0576114a0613782565b60200101906001600160f81b031916908160001a9053505b50806114c38161383c565b915050611359565b506000846040516020016114df9190613798565b60408051601f198184030181529190526014810151975090506001600160a01b03871661156e5760025b865181101561156c5786818151811061152457611524613782565b60209101015189906001600160f81b031916600360fc1b146115595760405162461bcd60e51b815260040161064a9190613007565b50806115648161383c565b915050611509565b505b50505050505092915050565b600081116115ca5760405162461bcd60e51b815260206004820152601f60248201527f416d6f756e74206c657373207468616e206d696e696d756d20616d6f756e7400604482015260640161064a565b6115d48382611f14565b6001600160a01b038316611650576040516000906001600160a01b0384169083156108fc0290849084818181858888f193505050509050806105965760405162461bcd60e51b81526020600482015260156024820152744661696c656420746f2073656e6420746f6b656e7360581b604482015260640161064a565b610b4a6001600160a01b0384168383611fb0565b60408051606081018252600080825260208083018290528284018290528351808501855282815281018290528351808501909452845184528481019084015290916116ae90611c40565b905060405180606001604052806116de836001815181106116d1576116d1613782565b6020026020010151611fe1565b6001600160a01b031681526020016117028360028151811061127e5761127e613782565b815260200161171d836003815181106116d1576116d1613782565b6001600160a01b031690529392505050565b8234101561177f5760405162461bcd60e51b815260206004820152601f60248201527f416d6f756e74206c657373207468616e206d696e696d756d20616d6f756e7400604482015260640161064a565b600061178b8434613829565b9050610596600085858585611a55565b336117cd7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610b615760405163118cdaa760e01b815233600482015260240161064a565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b61186f612034565b610b3c8161207d565b60006001600160a01b03821661188f575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156118d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c59190613769565b6001600160a01b038116600090815260046020908152604080832054600590925282205481830361192d576000925050506111c5565b600061271061193c8388613728565b6119469190613755565b905060006119548288613829565b6001600160a01b0387166000908152600660205260408120549192509061197b9042613829565b90506119878186612085565b90506000856119968385613728565b6119a09190613755565b6001600160a01b038916600090815260076020526040812054919250906119c8908390613829565b90506119d48a82612085565b90506119e0818661209b565b9a9950505050505050505050565b6040516001600160a01b0384811660248301528381166044830152606482018390526105969186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506120aa565b60006040518060a00160405280611a74886001600160a01b031661210d565b8152602001611a823361210d565b815260200185815260200186815260200184815250905060006040518060600160405280886001600160a01b03168152602001878152602001336001600160a01b031681525090506000600360009054906101000a90046001600160a01b03166001600160a01b031663f434bb686040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b1f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b4791908101906138f3565b6000549091506001600160a01b031663edc6afff856002611b6787612118565b611b70876121b2565b865160208801516040516001600160e01b031960e089901b168152611b9c9594939291906004016139e1565b60206040518083038185885af1158015611bba573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611bdf9190613769565b505050505050505050565b611bf38261222e565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115611c3857610b4a8282612293565b6105c6612309565b6060611c4b82612328565b611c885760405162461bcd60e51b815260206004820152600e60248201526d135d5cdd0818994818481b1a5cdd60921b604482015260640161064a565b6000611c9383612363565b90506000816001600160401b03811115611caf57611caf61301a565b604051908082528060200260200182016040528015611cf457816020015b6040805180820190915260008082526020820152815260200190600190039081611ccd5790505b5090506000611d0685602001516123e8565b8560200151611d1591906137b4565b90506000805b84811015611d7e57611d2c83612469565b9150604051806040016040528083815260200184815250848281518110611d5557611d55613782565b6020908102919091010152611d6a82846137b4565b925080611d768161383c565b915050611d1b565b509195945050505050565b8051606090611dcb5760405162461bcd60e51b815260206004820152600e60248201526d092dcecc2d8d2c840d8cadccee8d60931b604482015260640161064a565b6000611dda83602001516123e8565b90506000818460000151611dee9190613829565b90506000816001600160401b03811115611e0a57611e0a61301a565b6040519080825280601f01601f191660200182016040528015611e34576020820181803683370190505b5090506000816020019050611e59848760200151611e5291906137b4565b8285612512565b50949350505050565b805160009015801590611e7757508151602110155b611eb95760405162461bcd60e51b815260206004820152601360248201527224b73b30b634b2103ab4b73a10373ab6b132b960691b604482015260640161064a565b6000611ec883602001516123e8565b90506000818460000151611edc9190613829565b9050600080838660200151611ef191906137b4565b9050805191506020831015611e5957506020919091036101000a90049392505050565b6000611f1f83611878565b90506000611f2d82856118f7565b905080611f3a8484613829565b1015611f815760405162461bcd60e51b8152602060048201526016602482015275195e18d959591cc81dda5d1a191c985dc81b1a5b5a5d60521b604482015260640161064a565b6001600160a01b0390931660009081526007602090815260408083209590955560069052929092204290555050565b6040516001600160a01b03838116602483015260448201839052610b4a91859182169063a9059cbb90606401611a23565b805160009060151461202b5760405162461bcd60e51b81526020600482015260136024820152724d7573742068617665206c656e67746820323160681b604482015260640161064a565b6111c582611e62565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610b6157604051631afcd79f60e31b815260040160405180910390fd5b610ee0612034565b60008183106120945781610ed1565b5090919050565b60008183116120945781610ed1565b60006120bf6001600160a01b03841683612594565b905080516000141580156120e45750808060200190518101906120e2919061356a565b155b15610b4a57604051635274afe760e01b81526001600160a01b038416600482015260240161064a565b60606111c5826125a2565b606060006121446040518060400160405280600781526020016611195c1bdcda5d60ca1b815250612777565b835161214f90612777565b61215c8560200151612777565b6121698660400151612777565b6121768760600151612782565b6121838860800151612790565b60405160200161219896959493929190613ab3565b6040516020818303038152906040529050610ed1816127ff565b606060006121e46040518060400160405280600d81526020016c11195c1bdcda5d14995d995c9d609a1b815250612777565b83516121f8906001600160a01b0316612835565b6122058560200151612782565b61221b86604001516001600160a01b0316612835565b6040516020016121989493929190613b32565b806001600160a01b03163b60000361226457604051634c9c8ce360e01b81526001600160a01b038216600482015260240161064a565b600080516020613d1783398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516122b09190613798565b600060405180830381855af49150503d80600081146122eb576040519150601f19603f3d011682016040523d82523d6000602084013e6122f0565b606091505b5091509150612300858383612858565b95945050505050565b3415610b615760405163b398979f60e01b815260040160405180910390fd5b8051600090810361233b57506000919050565b6020820151805160001a9060c0821015612359575060009392505050565b5060019392505050565b8051600090810361237657506000919050565b60008061238684602001516123e8565b846020015161239591906137b4565b90506000846000015185602001516123ad91906137b4565b90505b808210156123df576123c182612469565b6123cb90836137b4565b9150826123d78161383c565b9350506123b0565b50909392505050565b8051600090811a60808110156124015750600092915050565b60b881108061241c575060c0811080159061241c575060f881105b1561242a5750600192915050565b60c08110156124575761243f600160b86137db565b61244c9060ff1682613829565b610ed19060016137b4565b61243f600160f86137db565b50919050565b80516000908190811a6080811015612484576001915061250b565b60b88110156124aa57612498608082613829565b6124a39060016137b4565b915061250b565b60c08110156124d75760b78103600185019450806020036101000a8551046001820181019350505061250b565b60f88110156124eb5761249860c082613829565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b8060000361251f57505050565b6020811061255757825182526125366020846137b4565b92506125436020836137b4565b9150612550602082613829565b905061251f565b8015610b4a576000600161256c836020613829565b61257890610100613c6d565b6125829190613829565b84518451821691191617835250505050565b6060610ed1838360006128ad565b604080516028808252606082810190935283831b9160009160208201818036833701905050905060008060008060008060006125dd8b61294a565b905060005b6014811015612746576125f6816013613829565b612601906008613728565b61260c906002613c6d565b61261a9060608c901c613755565b9750612627601089613c79565b96506126348760106137f4565b61263e90896137db565b95508161264c826002613728565b6028811061265c5761265c613782565b602002015194508161266f826002613728565b61267a9060016137b4565b6028811061268a5761268a613782565b6020020151935061269b8786612adb565b92506126a78388613810565b60f81b896126b6836002613728565b815181106126c6576126c6613782565b60200101906001600160f81b031916908160001a9053506126e78685612adb565b92506126f38387613810565b60f81b89612702836002613728565b61270d9060016137b4565b8151811061271d5761271d613782565b60200101906001600160f81b031916908160001a9053508061273e8161383c565b9150506125e2565b50876040516020016127589190613c9b565b6040516020818303038152906040529950505050505050505050919050565b60606111c582612790565b60606111c561279083612b08565b606080825160011480156127be57506080836000815181106127b4576127b4613782565b016020015160f81c105b156127ca5750816111c5565b6127d683516080612bbc565b836040516020016127e8929190613cc5565b604051602081830303815290604052905092915050565b606061280d825160c0612bbc565b8260405160200161281f929190613cc5565b6040516020818303038152906040529050919050565b60408051600560a21b8318601482015260348101909152606090610ed181612790565b60608261286d5761286882612d72565b610ed1565b815115801561288457506001600160a01b0384163b155b1561250b57604051639996b31560e01b81526001600160a01b038516600482015260240161064a565b6060814710156128d25760405163cd78605960e01b815230600482015260240161064a565b600080856001600160a01b031684866040516128ee9190613798565b60006040518083038185875af1925050503d806000811461292b576040519150601f19603f3d011682016040523d82523d6000602084013e612930565b606091505b5091509150612940868383612858565b9695505050505050565b612952612f61565b606082901b600061296282612d9b565b6040516020016129729190613798565b60405160208183030381529060405280519060200120905060008060008060005b6014811015612acf5760108782601481106129b0576129b0613782565b6129bc9291901a613cf4565b93506010848883601481106129d3576129d3613782565b6129df9291901a6137db565b6129e99190613c79565b945060108682602081106129ff576129ff613782565b612a0b9291901a613cf4565b9150601082878360208110612a2257612a22613782565b612a2e9291901a6137db565b612a389190613c79565b925060098560ff16118015612a50575060078360ff16115b88612a5c836002613728565b60288110612a6c57612a6c613782565b91151560209092020152600960ff8516118015612a8c575060078260ff16115b88612a98836002613728565b612aa39060016137b4565b60288110612ab357612ab3613782565b9115156020909202015280612ac78161383c565b915050612993565b50505050505050919050565b6000600a8360ff161015612af1575060306111c5565b8115612aff575060376111c5565b50605792915050565b606081600003612b3557604080516001808252818301909252906020820181803683370190505092915050565b608060015b6020811015612b765781841015612b5d57612b558482612ef5565b949350505050565b60089190911b9080612b6e8161383c565b915050612b3a565b5080831015612ba3576040805160208101859052015b604051602081830303815290604052915050919050565b6040516000602082015260218101849052604101612b8c565b6060806038841015612c265760408051600180825281830190925290602082018180368337019050509050612bf183856137b4565b601f1a60f81b81600081518110612c0a57612c0a613782565b60200101906001600160f81b031916908160001a905350610ed1565b600060015b612c358187613755565b15612c5b5781612c448161383c565b9250612c54905061010082613728565b9050612c2b565b612c668260016137b4565b6001600160401b03811115612c7d57612c7d61301a565b6040519080825280601f01601f191660200182016040528015612ca7576020820181803683370190505b509250612cb485836137b4565b612cbf9060376137b4565b601f1a60f81b83600081518110612cd857612cd8613782565b60200101906001600160f81b031916908160001a905350600190505b818111612d6957610100612d088284613829565b612d1490610100613c6d565b612d1e9088613755565b612d2891906137c7565b601f1a60f81b838281518110612d4057612d40613782565b60200101906001600160f81b031916908160001a90535080612d618161383c565b915050612cf4565b50509392505050565b805115612d825780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60408051602880825260608281019093526000919060208201818036833701905050905060008080805b6014811015612eea57612dd9816013613829565b612de4906008613728565b612def906002613c6d565b612dfd90606089901c613755565b9350612e0a601085613c79565b9250612e178360106137f4565b612e2190856137db565b9150600a8360ff1610612e35576057612e38565b60305b612e429084613810565b60f81b85612e51836002613728565b81518110612e6157612e61613782565b60200101906001600160f81b031916908160001a905350600a8260ff1610612e8a576057612e8d565b60305b612e979083613810565b60f81b85612ea6836002613728565b612eb19060016137b4565b81518110612ec157612ec1613782565b60200101906001600160f81b031916908160001a90535080612ee28161383c565b915050612dc5565b509295945050505050565b60606000826001600160401b03811115612f1157612f1161301a565b6040519080825280601f01601f191660200182016040528015612f3b576020820181803683370190505b50905060208101836020035b6020811015612d695785811a825360019182019101612f47565b6040518061050001604052806028906020820280368337509192915050565b80356001600160a01b0381168114612f9757600080fd5b919050565b600060208284031215612fae57600080fd5b610ed182612f80565b60005b83811015612fd2578181015183820152602001612fba565b50506000910152565b60008151808452612ff3816020860160208601612fb7565b601f01601f19169290920160200192915050565b602081526000610ed16020830184612fdb565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156130585761305861301a565b604052919050565b60006001600160401b038211156130795761307961301a565b50601f01601f191660200190565b600082601f83011261309857600080fd5b81356130ab6130a682613060565b613030565b8181528460208386010111156130c057600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156130f357600080fd5b6130fc85612f80565b93506020850135925060408501356001600160401b038082111561311f57600080fd5b61312b88838901613087565b9350606087013591508082111561314157600080fd5b5061314e87828801613087565b91505092959194509250565b6000806040838503121561316d57600080fd5b61317683612f80565b946020939093013593505050565b6000806040838503121561319757600080fd5b6131a083612f80565b915060208301356001600160401b038111156131bb57600080fd5b6131c785828601613087565b9150509250929050565b60008083601f8401126131e357600080fd5b5081356001600160401b038111156131fa57600080fd5b60208301915083602082850101111561321257600080fd5b9250929050565b6000806000806000806060878903121561323257600080fd5b86356001600160401b038082111561324957600080fd5b6132558a838b016131d1565b9098509650602089013591508082111561326e57600080fd5b61327a8a838b016131d1565b9096509450604089013591508082111561329357600080fd5b818901915089601f8301126132a757600080fd5b8135818111156132b657600080fd5b8a60208260051b85010111156132cb57600080fd5b6020830194508093505050509295509295509295565b6000602082840312156132f357600080fd5b5035919050565b60008060006060848603121561330f57600080fd5b8335925060208401356001600160401b038082111561332d57600080fd5b61333987838801613087565b9350604086013591508082111561334f57600080fd5b5061335c86828701613087565b9150509250925092565b60008060006060848603121561337b57600080fd5b61338484612f80565b925060208401356001600160401b0381111561339f57600080fd5b6133ab86828701613087565b9250506133ba60408501612f80565b90509250925092565b6000806000606084860312156133d857600080fd5b6133e184612f80565b95602085013595506040909401359392505050565b60008060006060848603121561340b57600080fd5b61341484612f80565b92506020840135915060408401356001600160401b0381111561343657600080fd5b61335c86828701613087565b6000806040838503121561345557600080fd5b8235915060208301356001600160401b038111156131bb57600080fd5b600181811c9082168061348657607f821691505b60208210810361246357634e487b7160e01b600052602260045260246000fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208082528181018390526000906040600585901b8401810190840186845b8781101561355d57868403603f190183528135368a9003601e1901811261351457600080fd5b890185810190356001600160401b0381111561352f57600080fd5b80360382131561353e57600080fd5b6135498682846134a6565b9550505091840191908401906001016134ee565b5091979650505050505050565b60006020828403121561357c57600080fd5b81518015158114610ed157600080fd5b600082601f83011261359d57600080fd5b81516135ab6130a682613060565b8181528460208386010111156135c057600080fd5b612b55826020830160208701612fb7565b6000602082840312156135e357600080fd5b81516001600160401b038111156135f957600080fd5b612b558482850161358c565b601f821115610b4a57600081815260208120601f850160051c8101602086101561362c5750805b601f850160051c820191505b8181101561364b57828155600101613638565b505050505050565b81516001600160401b0381111561366c5761366c61301a565b6136808161367a8454613472565b84613605565b602080601f8311600181146136b5576000841561369d5750858301515b600019600386901b1c1916600185901b17855561364b565b600085815260208120601f198616915b828110156136e4578886015182559484019460019091019084016136c5565b50858210156137025787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176111c5576111c5613712565b634e487b7160e01b600052601260045260246000fd5b6000826137645761376461373f565b500490565b60006020828403121561377b57600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600082516137aa818460208701612fb7565b9190910192915050565b808201808211156111c5576111c5613712565b6000826137d6576137d661373f565b500690565b60ff82811682821603908111156111c5576111c5613712565b60ff818116838216029081169081811461250b5761250b613712565b60ff81811683821601908111156111c5576111c5613712565b818103818111156111c5576111c5613712565b60006001820161384e5761384e613712565b5060010190565b600082601f83011261386657600080fd5b815160206001600160401b03808311156138825761388261301a565b8260051b613891838201613030565b93845285810183019383810190888611156138ab57600080fd5b84880192505b858310156138e7578251848111156138c95760008081fd5b6138d78a87838c010161358c565b83525091840191908401906138b1565b98975050505050505050565b60006020828403121561390557600080fd5b81516001600160401b038082111561391c57600080fd5b908301906040828603121561393057600080fd5b60405160408101818110838211171561394b5761394b61301a565b60405282518281111561395d57600080fd5b61396987828601613855565b82525060208301518281111561397e57600080fd5b61398a87828601613855565b60208301525095945050505050565b600081518084526020808501808196508360051b8101915082860160005b8581101561355d5782840389526139cf848351612fdb565b988501989350908401906001016139b7565b60a0815260008087546139f381613472565b8060a086015260c0600180841660008114613a155760018114613a2f57613a60565b60ff1985168884015283151560051b880183019550613a60565b8c60005260208060002060005b86811015613a575781548b8201870152908401908201613a3c565b8a018501975050505b50505050508281036020840152613a778188612fdb565b90508281036040840152613a8b8187612fdb565b90508281036060840152613a9f8186613999565b905082810360808401526138e78185613999565b600087516020613ac68285838d01612fb7565b885191840191613ad98184848d01612fb7565b8851920191613aeb8184848c01612fb7565b8751920191613afd8184848b01612fb7565b8651920191613b0f8184848a01612fb7565b8551920191613b218184848901612fb7565b919091019998505050505050505050565b60008551613b44818460208a01612fb7565b855190830190613b58818360208a01612fb7565b8551910190613b6b818360208901612fb7565b8451910190613b7e818360208801612fb7565b019695505050505050565b600181815b80851115613bc4578160001904821115613baa57613baa613712565b80851615613bb757918102915b93841c9390800290613b8e565b509250929050565b600082613bdb575060016111c5565b81613be8575060006111c5565b8160018114613bfe5760028114613c0857613c24565b60019150506111c5565b60ff841115613c1957613c19613712565b50506001821b6111c5565b5060208310610133831016604e8410600b8410161715613c47575081810a6111c5565b613c518383613b89565b8060001904821115613c6557613c65613712565b029392505050565b6000610ed18383613bcc565b600060ff831680613c8c57613c8c61373f565b8060ff84160491505092915050565b61060f60f31b815260008251613cb8816002850160208701612fb7565b9190910160020192915050565b60008351613cd7818460208801612fb7565b835190830190613ceb818360208801612fb7565b01949350505050565b600060ff831680613d0757613d0761373f565b8060ff8416069150509291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca264697066735822122016355eb5cd96b06d4f2dbf0184d802f3eab8eeec53bf3f1a9092370c22523d3064736f6c63430008150033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.