Source Code
Latest 25 from a total of 1,434 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Send To | 136764118 | 233 days ago | IN | 0.001140995357612 ETH | 0.00000003263 | ||||
| Send To | 136764083 | 233 days ago | IN | 0.000380391811118 ETH | 0.000000032984 | ||||
| Send To | 136764011 | 233 days ago | IN | 0.000380610548344 ETH | 0.000000033997 | ||||
| Send To | 136763900 | 233 days ago | IN | 0.000038005858091 ETH | 0.000000036723 | ||||
| Send To | 136687932 | 234 days ago | IN | 0.000038239949253 ETH | 0.000000051506 | ||||
| Send To | 136686485 | 234 days ago | IN | 0.000189997122873 ETH | 0.000000098372 | ||||
| Send To | 136686429 | 234 days ago | IN | 0.000038007521027 ETH | 0.000000103742 | ||||
| Send To | 136686384 | 234 days ago | IN | 0.000038019230434 ETH | 0.000000099588 | ||||
| Send To | 136686321 | 234 days ago | IN | 0.000076026871368 ETH | 0.000000111496 | ||||
| Send To | 136686121 | 234 days ago | IN | 0.000038089293056 ETH | 0.000000158708 | ||||
| Send To | 136686104 | 234 days ago | IN | 0.00003810014299 ETH | 0.000000144637 | ||||
| Send To | 136417011 | 241 days ago | IN | 0.000150587245788 ETH | 0.000000038688 | ||||
| Send To | 136390731 | 241 days ago | IN | 0.000186657831132 ETH | 0.000000072242 | ||||
| Send To | 136390611 | 241 days ago | IN | 0.000186749913423 ETH | 0.000000093569 | ||||
| Send To | 136390525 | 241 days ago | IN | 0.000186595787551 ETH | 0.000000116568 | ||||
| Send To | 136387838 | 241 days ago | IN | 0.000186239217506 ETH | 0.000000081128 | ||||
| Send To | 136387798 | 241 days ago | IN | 0.000186130866293 ETH | 0.000000068967 | ||||
| Send To | 136387687 | 241 days ago | IN | 0.00018614134382 ETH | 0.00000006152 | ||||
| Send To | 136387538 | 241 days ago | IN | 0.000185919357233 ETH | 0.000000055591 | ||||
| Send To | 136387224 | 241 days ago | IN | 0.000186304764391 ETH | 0.000000054375 | ||||
| Send To | 136386924 | 241 days ago | IN | 0.000186381735476 ETH | 0.000000059843 | ||||
| Send To | 136385646 | 241 days ago | IN | 0.003700070573367 ETH | 0.000000043775 | ||||
| Send To | 136385537 | 241 days ago | IN | 0.003696874384877 ETH | 0.000000048661 | ||||
| Send To | 136385374 | 241 days ago | IN | 0.003693695135874 ETH | 0.000000061657 | ||||
| Send To | 136384868 | 241 days ago | IN | 0.003697265161338 ETH | 0.000000072383 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 136764118 | 233 days ago | 0.001129585404036 ETH | ||||
| 136764083 | 233 days ago | 0.000376587893007 ETH | ||||
| 136764011 | 233 days ago | 0.000376804442861 ETH | ||||
| 136763900 | 233 days ago | 0.00003762579951 ETH | ||||
| 136687932 | 234 days ago | 0.00003785754976 ETH | ||||
| 136686485 | 234 days ago | 0.000188097151644 ETH | ||||
| 136686429 | 234 days ago | 0.000037627445817 ETH | ||||
| 136686384 | 234 days ago | 0.00003763903813 ETH | ||||
| 136686321 | 234 days ago | 0.000075266602655 ETH | ||||
| 136686121 | 234 days ago | 0.000037708400125 ETH | ||||
| 136686104 | 234 days ago | 0.00003771914156 ETH | ||||
| 136417011 | 241 days ago | 0.00014908137333 ETH | ||||
| 136390731 | 241 days ago | 0.000184791252821 ETH | ||||
| 136390611 | 241 days ago | 0.000184882414289 ETH | ||||
| 136390525 | 241 days ago | 0.000184729829675 ETH | ||||
| 136387838 | 241 days ago | 0.000184376825331 ETH | ||||
| 136387798 | 241 days ago | 0.00018426955763 ETH | ||||
| 136387687 | 241 days ago | 0.000184279930382 ETH | ||||
| 136387538 | 241 days ago | 0.000184060163661 ETH | ||||
| 136387224 | 241 days ago | 0.000184441716748 ETH | ||||
| 136386924 | 241 days ago | 0.000184517918121 ETH | ||||
| 136385646 | 241 days ago | 0.003663069867633 ETH | ||||
| 136385537 | 241 days ago | 0.003659905641029 ETH | ||||
| 136385374 | 241 days ago | 0.003656758184515 ETH | ||||
| 136384868 | 241 days ago | 0.003660292509725 ETH |
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:
TippingPG
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import { ITipping } from "./interfaces/ITipping.sol";
import { MultiAssetSender } from "./libs/MultiAssetSender.sol";
import { FeeCalculator } from "./libs/FeeCalculator.sol";
import { PublicGoodAttester } from "./libs/Attestation.sol";
import { Batchable } from "./libs/Batchable.sol";
import { AssetType, FeeType } from "./enums/IDrissEnums.sol";
error tipping__withdraw__OnlyAdminCanWithdraw();
/**
* @title Tipping
* @author Lennard (lennardevertz)
* @custom:contributor Rafał Kalinowski <[email protected]>
* @notice Tipping is a helper smart contract used for IDriss social media tipping functionality
* @notice This contract has minor changes specifically for Optimism featuring Gitcoin Public Good Attestations
*/
contract TippingPG is Ownable, ITipping, MultiAssetSender, FeeCalculator, PublicGoodAttester, Batchable, IERC165 {
address public contractOwner;
mapping(address => bool) public admins;
mapping(address => bool) public publicGoods;
event TipMessage(
address indexed recipientAddress,
string message,
address indexed sender,
address indexed tokenAddress,
uint256 fee
);
constructor(address _nativeUsdAggregator, address _eas) FeeCalculator(_nativeUsdAggregator) PublicGoodAttester(_eas) {
admins[msg.sender] = true;
FEE_TYPE_MAPPING[AssetType.Coin] = FeeType.Percentage;
FEE_TYPE_MAPPING[AssetType.Token] = FeeType.Percentage;
FEE_TYPE_MAPPING[AssetType.NFT] = FeeType.Constant;
FEE_TYPE_MAPPING[AssetType.ERC1155] = FeeType.Constant;
}
/**
* @notice Send native currency tip, charging a small fee
*/
function sendTo(
address _recipient,
uint256, // amount is used only for multicall
string memory _message
) external payable override {
uint256 msgValue = _MSG_VALUE > 0 ? _MSG_VALUE : msg.value;
(, uint256 paymentValue) = _splitPayment(msgValue, AssetType.Coin);
if (publicGoods[_recipient]) {
paymentValue = msgValue;
_attestDonor(_recipient);
}
_sendCoin(_recipient, paymentValue);
emit TipMessage(_recipient, _message, msg.sender, address(0), msgValue-paymentValue);
}
/**
* @notice Send a tip in ERC20 token, charging a small fee
*/
function sendTokenTo(
address _recipient,
uint256 _amount,
address _tokenContractAddr,
string memory _message
) external payable override {
(, uint256 paymentValue) = _splitPayment(_amount, AssetType.Token);
if (publicGoods[_recipient]) {
paymentValue = _amount;
_attestDonor(_recipient);
}
_sendTokenAssetFrom(_amount, msg.sender, address(this), _tokenContractAddr);
_sendTokenAsset(paymentValue, _recipient, _tokenContractAddr);
emit TipMessage(_recipient, _message, msg.sender, _tokenContractAddr, _amount-paymentValue);
}
/**
* @notice Send a tip in ERC721 token, charging a small $ fee
*/
function sendERC721To(
address _recipient,
uint256 _tokenId,
address _nftContractAddress,
string memory _message
) external payable override {
// we use it just to revert when value is too small
uint256 msgValue = _MSG_VALUE > 0 ? _MSG_VALUE : msg.value;
(uint256 fee,) = _splitPayment(msgValue, AssetType.NFT);
_sendNFTAsset(_tokenId, msg.sender, _recipient, _nftContractAddress);
emit TipMessage(_recipient, _message, msg.sender, _nftContractAddress, fee);
}
/**
* @notice Send a tip in ERC721 token, charging a small $ fee
*/
function sendERC1155To(
address _recipient,
uint256 _assetId,
uint256 _amount,
address _assetContractAddress,
string memory _message
) external payable override {
// we use it just to revert when value is too small
uint256 msgValue = _MSG_VALUE > 0 ? _MSG_VALUE : msg.value;
(uint256 fee,) = _splitPayment(msgValue, AssetType.ERC1155);
_sendERC1155Asset(_assetId, _amount, msg.sender, _recipient, _assetContractAddress);
emit TipMessage(_recipient, _message, msg.sender, _assetContractAddress, fee);
}
/**
* @notice Withdraw native currency transfer fees
*/
function withdraw() external override onlyAdminCanWithdraw {
(bool success, ) = msg.sender.call{value: address(this).balance}("");
require(success, "Failed to withdraw.");
}
modifier onlyAdminCanWithdraw() {
if (admins[msg.sender] != true) {
revert tipping__withdraw__OnlyAdminCanWithdraw();
}
_;
}
/**
* @notice Withdraw ERC20 transfer fees
*/
function withdrawToken(address _tokenContract)
external
override
onlyAdminCanWithdraw
{
IERC20 withdrawTC = IERC20(_tokenContract);
withdrawTC.transfer(msg.sender, withdrawTC.balanceOf(address(this)));
}
/**
* @notice Add admin with priviledged access
*/
function addAdmin(address _adminAddress)
external
override
onlyOwner
{
admins[_adminAddress] = true;
}
/**
* @notice Remove admin
*/
function deleteAdmin(address _adminAddress)
external
override
onlyOwner
{
admins[_adminAddress] = false;
}
/**
* @notice Add public goods address with priviledged fee structure
*/
function addPublicGood(address publicGoodAddress) external onlyOwner {
publicGoods[publicGoodAddress] = true;
}
/**
* @notice Remove public goods address
*/
function deletePublicGood(address publicGoodAddress) external onlyOwner {
delete publicGoods[publicGoodAddress];
}
/**
* @notice This is a function that allows for multicall
* @param _calls An array of inputs for each call.
* @dev calls Batchable::callBatch
*/
function batch(bytes[] calldata _calls) external payable {
batchCall(_calls);
}
function isMsgValueOverride(bytes4 _selector) override pure internal returns (bool) {
return
_selector == this.sendTo.selector ||
_selector == this.sendTokenTo.selector ||
_selector == this.sendERC721To.selector ||
_selector == this.sendERC1155To.selector
;
}
function calculateMsgValueForACall(bytes4 _selector, bytes memory _calldata) override view internal returns (uint256) {
uint256 currentCallPriceAmount;
if (_selector == this.sendTo.selector) {
assembly {
currentCallPriceAmount := mload(add(_calldata, 68))
}
} else if (_selector == this.sendTokenTo.selector) {
currentCallPriceAmount = getPaymentFee(0, AssetType.Token);
} else if (_selector == this.sendTokenTo.selector) {
currentCallPriceAmount = getPaymentFee(0, AssetType.NFT);
} else {
currentCallPriceAmount = getPaymentFee(0, AssetType.ERC1155);
}
return currentCallPriceAmount;
}
/*
* @notice Always reverts. By default Ownable supports renouncing ownership, that is setting owner to address 0.
* However in this case it would disallow receiving payment fees by anyone.
*/
function renounceOwnership() public override view onlyOwner {
revert("Operation not supported");
}
/**
* @notice ERC165 interface function implementation, listing all supported interfaces
*/
function supportsInterface (bytes4 interfaceId) public pure override returns (bool) {
return interfaceId == type(IERC165).interfaceId
|| interfaceId == type(ITipping).interfaceId;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
function getRoundData(uint80 _roundId)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. 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 {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
enum AssetType {
Coin,
Token,
NFT,
ERC1155
}
/**
* Percentage - constant percentage, e.g. 1% of the msg.value
* PercentageOrConstantMaximum - get msg.value percentage, or constant dollar value, depending on what is bigger
* Constant - constant dollar value, e.g. $1 - uses price Oracle
*/
enum FeeType {
Percentage,
PercentageOrConstantMaximum,
Constant
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { ISchemaRegistry } from "./ISchemaRegistry.sol";
import { Attestation, EIP712Signature } from "../libs/Common.sol";
/// @notice A struct representing the arguments of the attestation request.
struct AttestationRequestData {
address recipient; // The recipient of the attestation.
uint64 expirationTime; // The time when the attestation expires (Unix timestamp).
bool revocable; // Whether the attestation is revocable.
bytes32 refUID; // The UID of the related attestation.
bytes data; // Custom attestation data.
uint256 value; // An explicit ETH amount to send to the resolver. This is important to prevent accidental user errors.
}
/// @notice A struct representing the full arguments of the attestation request.
struct AttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData data; // The arguments of the attestation request.
}
/// @notice A struct representing the full arguments of the full delegated attestation request.
struct DelegatedAttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData data; // The arguments of the attestation request.
EIP712Signature signature; // The EIP712 signature data.
address attester; // The attesting account.
}
/// @notice A struct representing the full arguments of the multi attestation request.
struct MultiAttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData[] data; // The arguments of the attestation request.
}
/// @notice A struct representing the full arguments of the delegated multi attestation request.
struct MultiDelegatedAttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData[] data; // The arguments of the attestation requests.
EIP712Signature[] signatures; // The EIP712 signatures data. Please note that the signatures are assumed to be signed with increasing nonces.
address attester; // The attesting account.
}
/// @notice A struct representing the arguments of the revocation request.
struct RevocationRequestData {
bytes32 uid; // The UID of the attestation to revoke.
uint256 value; // An explicit ETH amount to send to the resolver. This is important to prevent accidental user errors.
}
/// @notice A struct representing the full arguments of the revocation request.
struct RevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData data; // The arguments of the revocation request.
}
/// @notice A struct representing the arguments of the full delegated revocation request.
struct DelegatedRevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData data; // The arguments of the revocation request.
EIP712Signature signature; // The EIP712 signature data.
address revoker; // The revoking account.
}
/// @notice A struct representing the full arguments of the multi revocation request.
struct MultiRevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData[] data; // The arguments of the revocation request.
}
/// @notice A struct representing the full arguments of the delegated multi revocation request.
struct MultiDelegatedRevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData[] data; // The arguments of the revocation requests.
EIP712Signature[] signatures; // The EIP712 signatures data. Please note that the signatures are assumed to be signed with increasing nonces.
address revoker; // The revoking account.
}
/// @title IEAS
/// @notice EAS - Ethereum Attestation Service interface.
interface IEAS {
/// @notice Emitted when an attestation has been made.
/// @param recipient The recipient of the attestation.
/// @param attester The attesting account.
/// @param uid The UID the revoked attestation.
/// @param schema The UID of the schema.
event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schema);
/// @notice Emitted when an attestation has been revoked.
/// @param recipient The recipient of the attestation.
/// @param attester The attesting account.
/// @param schema The UID of the schema.
/// @param uid The UID the revoked attestation.
event Revoked(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schema);
/// @notice Emitted when a data has been timestamped.
/// @param data The data.
/// @param timestamp The timestamp.
event Timestamped(bytes32 indexed data, uint64 indexed timestamp);
/// @notice Emitted when a data has been revoked.
/// @param revoker The address of the revoker.
/// @param data The data.
/// @param timestamp The timestamp.
event RevokedOffchain(address indexed revoker, bytes32 indexed data, uint64 indexed timestamp);
/// @notice Returns the address of the global schema registry.
/// @return The address of the global schema registry.
function getSchemaRegistry() external view returns (ISchemaRegistry);
/// @notice Attests to a specific schema.
/// @param request The arguments of the attestation request.
/// @return The UID of the new attestation.
///
/// Example:
/// attest({
/// schema: "0facc36681cbe2456019c1b0d1e7bedd6d1d40f6f324bf3dd3a4cef2999200a0",
/// data: {
/// recipient: "0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf",
/// expirationTime: 0,
/// revocable: true,
/// refUID: "0x0000000000000000000000000000000000000000000000000000000000000000",
/// data: "0xF00D",
/// value: 0
/// }
/// })
function attest(AttestationRequest calldata request) external payable returns (bytes32);
/// @notice Attests to a specific schema via the provided EIP712 signature.
/// @param delegatedRequest The arguments of the delegated attestation request.
/// @return The UID of the new attestation.
///
/// Example:
/// attestByDelegation({
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: {
/// recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
/// expirationTime: 1673891048,
/// revocable: true,
/// refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
/// data: '0x1234',
/// value: 0
/// },
/// signature: {
/// v: 28,
/// r: '0x148c...b25b',
/// s: '0x5a72...be22'
/// },
/// attester: '0xc5E8740aD971409492b1A63Db8d83025e0Fc427e'
/// })
function attestByDelegation(
DelegatedAttestationRequest calldata delegatedRequest
) external payable returns (bytes32);
/// @notice Attests to multiple schemas.
/// @param multiRequests The arguments of the multi attestation requests. The requests should be grouped by distinct
/// schema ids to benefit from the best batching optimization.
/// @return The UIDs of the new attestations.
///
/// Example:
/// multiAttest([{
/// schema: '0x33e9094830a5cba5554d1954310e4fbed2ef5f859ec1404619adea4207f391fd',
/// data: [{
/// recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
/// expirationTime: 1673891048,
/// revocable: true,
/// refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
/// data: '0x1234',
/// value: 1000
/// },
/// {
/// recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
/// expirationTime: 0,
/// revocable: false,
/// refUID: '0x480df4a039efc31b11bfdf491b383ca138b6bde160988222a2a3509c02cee174',
/// data: '0x00',
/// value: 0
/// }],
/// },
/// {
/// schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425',
/// data: [{
/// recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
/// expirationTime: 0,
/// revocable: true,
/// refUID: '0x75bf2ed8dca25a8190c50c52db136664de25b2449535839008ccfdab469b214f',
/// data: '0x12345678',
/// value: 0
/// },
/// }])
function multiAttest(MultiAttestationRequest[] calldata multiRequests) external payable returns (bytes32[] memory);
/// @notice Attests to multiple schemas using via provided EIP712 signatures.
/// @param multiDelegatedRequests The arguments of the delegated multi attestation requests. The requests should be
/// grouped by distinct schema ids to benefit from the best batching optimization.
/// @return The UIDs of the new attestations.
///
/// Example:
/// multiAttestByDelegation([{
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: [{
/// recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
/// expirationTime: 1673891048,
/// revocable: true,
/// refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
/// data: '0x1234',
/// value: 0
/// },
/// {
/// recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
/// expirationTime: 0,
/// revocable: false,
/// refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
/// data: '0x00',
/// value: 0
/// }],
/// signatures: [{
/// v: 28,
/// r: '0x148c...b25b',
/// s: '0x5a72...be22'
/// },
/// {
/// v: 28,
/// r: '0x487s...67bb',
/// s: '0x12ad...2366'
/// }],
/// attester: '0x1D86495b2A7B524D747d2839b3C645Bed32e8CF4'
/// }])
function multiAttestByDelegation(
MultiDelegatedAttestationRequest[] calldata multiDelegatedRequests
) external payable returns (bytes32[] memory);
/// @notice Revokes an existing attestation to a specific schema.
/// @param request The arguments of the revocation request.
///
/// Example:
/// revoke({
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: {
/// uid: '0x101032e487642ee04ee17049f99a70590c735b8614079fc9275f9dd57c00966d',
/// value: 0
/// }
/// })
function revoke(RevocationRequest calldata request) external payable;
/// @notice Revokes an existing attestation to a specific schema via the provided EIP712 signature.
/// @param delegatedRequest The arguments of the delegated revocation request.
///
/// Example:
/// revokeByDelegation({
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: {
/// uid: '0xcbbc12102578c642a0f7b34fe7111e41afa25683b6cd7b5a14caf90fa14d24ba',
/// value: 0
/// },
/// signature: {
/// v: 27,
/// r: '0xb593...7142',
/// s: '0x0f5b...2cce'
/// },
/// revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992'
/// })
function revokeByDelegation(DelegatedRevocationRequest calldata delegatedRequest) external payable;
/// @notice Revokes existing attestations to multiple schemas.
/// @param multiRequests The arguments of the multi revocation requests. The requests should be grouped by distinct
/// schema ids to benefit from the best batching optimization.
///
/// Example:
/// multiRevoke([{
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: [{
/// uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25',
/// value: 1000
/// },
/// {
/// uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade',
/// value: 0
/// }],
/// },
/// {
/// schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425',
/// data: [{
/// uid: '0x053d42abce1fd7c8fcddfae21845ad34dae287b2c326220b03ba241bc5a8f019',
/// value: 0
/// },
/// }])
function multiRevoke(MultiRevocationRequest[] calldata multiRequests) external payable;
/// @notice Revokes existing attestations to multiple schemas via provided EIP712 signatures.
/// @param multiDelegatedRequests The arguments of the delegated multi revocation attestation requests. The requests
/// should be grouped by distinct schema ids to benefit from the best batching optimization.
///
/// Example:
/// multiRevokeByDelegation([{
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: [{
/// uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25',
/// value: 1000
/// },
/// {
/// uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade',
/// value: 0
/// }],
/// signatures: [{
/// v: 28,
/// r: '0x148c...b25b',
/// s: '0x5a72...be22'
/// },
/// {
/// v: 28,
/// r: '0x487s...67bb',
/// s: '0x12ad...2366'
/// }],
/// revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992'
/// }])
function multiRevokeByDelegation(
MultiDelegatedRevocationRequest[] calldata multiDelegatedRequests
) external payable;
/// @notice Timestamps the specified bytes32 data.
/// @param data The data to timestamp.
/// @return The timestamp the data was timestamped with.
function timestamp(bytes32 data) external returns (uint64);
/// @notice Timestamps the specified multiple bytes32 data.
/// @param data The data to timestamp.
/// @return The timestamp the data was timestamped with.
function multiTimestamp(bytes32[] calldata data) external returns (uint64);
/// @notice Revokes the specified bytes32 data.
/// @param data The data to timestamp.
/// @return The timestamp the data was revoked with.
function revokeOffchain(bytes32 data) external returns (uint64);
/// @notice Revokes the specified multiple bytes32 data.
/// @param data The data to timestamp.
/// @return The timestamp the data was revoked with.
function multiRevokeOffchain(bytes32[] calldata data) external returns (uint64);
/// @notice Returns an existing attestation by UID.
/// @param uid The UID of the attestation to retrieve.
/// @return The attestation data members.
function getAttestation(bytes32 uid) external view returns (Attestation memory);
/// @notice Checks whether an attestation exists.
/// @param uid The UID of the attestation to retrieve.
/// @return Whether an attestation exists.
function isAttestationValid(bytes32 uid) external view returns (bool);
/// @notice Returns the timestamp that the specified data was timestamped with.
/// @param data The data to query.
/// @return The timestamp the data was timestamped with.
function getTimestamp(bytes32 data) external view returns (uint64);
/// @notice Returns the timestamp that the specified data was timestamped with.
/// @param data The data to query.
/// @return The timestamp the data was timestamped with.
function getRevokeOffchain(address revoker, bytes32 data) external view returns (uint64);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { ISchemaResolver } from "./resolver/ISchemaResolver.sol";
/// @notice A struct representing a record for a submitted schema.
struct SchemaRecord {
bytes32 uid; // The unique identifier of the schema.
ISchemaResolver resolver; // Optional schema resolver.
bool revocable; // Whether the schema allows revocations explicitly.
string schema; // Custom specification of the schema (e.g., an ABI).
}
/// @title ISchemaRegistry
/// @notice The global schema registry interface.
interface ISchemaRegistry {
/// @notice Emitted when a new schema has been registered
/// @param uid The schema UID.
/// @param registerer The address of the account used to register the schema.
event Registered(bytes32 indexed uid, address registerer);
/// @notice Submits and reserves a new schema
/// @param schema The schema data schema.
/// @param resolver An optional schema resolver.
/// @param revocable Whether the schema allows revocations explicitly.
/// @return The UID of the new schema.
function register(string calldata schema, ISchemaResolver resolver, bool revocable) external returns (bytes32);
/// @notice Returns an existing schema by UID
/// @param uid The UID of the schema to retrieve.
/// @return The schema data members.
function getSchema(bytes32 uid) external view returns (SchemaRecord memory);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import { AssetType } from "../enums/IDrissEnums.sol";
interface ITipping {
function sendTo(
address _recipient,
uint256 _amount,
string memory _message
) external payable;
function sendTokenTo(
address _recipient,
uint256 _amount,
address _tokenContractAddr,
string memory _message
) external payable;
function sendERC721To(
address _recipient,
uint256 _assetId,
address _nftContractAddress,
string memory _message
) external payable;
function sendERC1155To(
address _recipient,
uint256 _assetId,
uint256 _amount,
address _nftContractAddress,
string memory _message
) external payable;
function withdraw() external;
function withdrawToken(address _tokenContract) external;
function addAdmin(address _adminAddress) external;
function deleteAdmin(address _adminAddress) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Attestation } from "../../libs/Common.sol";
/// @title ISchemaResolver
/// @notice The interface of an optional schema resolver.
interface ISchemaResolver {
/// @notice Returns whether the resolver supports ETH transfers.
function isPayable() external pure returns (bool);
/// @notice Processes an attestation and verifies whether it's valid.
/// @param attestation The new attestation.
/// @return Whether the attestation is valid.
function attest(Attestation calldata attestation) external payable returns (bool);
/// @notice Processes multiple attestations and verifies whether they are valid.
/// @param attestations The new attestations.
/// @param values Explicit ETH amounts which were sent with each attestation.
/// @return Whether all the attestations are valid.
function multiAttest(
Attestation[] calldata attestations,
uint256[] calldata values
) external payable returns (bool);
/// @notice Processes an attestation revocation and verifies if it can be revoked.
/// @param attestation The existing attestation to be revoked.
/// @return Whether the attestation can be revoked.
function revoke(Attestation calldata attestation) external payable returns (bool);
/// @notice Processes revocation of multiple attestation and verifies they can be revoked.
/// @param attestations The existing attestations to be revoked.
/// @param values Explicit ETH amounts which were sent with each revocation.
/// @return Whether the attestations can be revoked.
function multiRevoke(
Attestation[] calldata attestations,
uint256[] calldata values
) external payable returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import { IEAS, AttestationRequest, AttestationRequestData } from "../interfaces/IEAS.sol";
import { NO_EXPIRATION_TIME, EMPTY_UID } from "./Common.sol";
/**
* @title Ethereum Attestation Service - Example
*/
contract PublicGoodAttester {
error InvalidEAS();
// The address of the global EAS contract.
IEAS private immutable _eas;
/**
* @dev Creates a new ExampleAttester instance.
*
* @param eas The address of the global EAS contract.
*/
constructor(address eas) {
if (eas == address(0)) {
revert InvalidEAS();
}
_eas = IEAS(eas);
}
/**
* @dev Attests to a schema that receives parameter
* @param _publicGood: recipient address of public good
* @return The UID of the new attestation.
*/
function _attestDonor(address _publicGood) internal returns (bytes32) {
return
_eas.attest(
AttestationRequest({
schema: 0x28b73429cc730191053ba7fe21e17253be25dbab480f0c3a369de5217657d925,
data: AttestationRequestData({
recipient: msg.sender, // the supporter receives the attestation
expirationTime: NO_EXPIRATION_TIME, // No expiration time
revocable: false,
refUID: EMPTY_UID, // No references UI
data: abi.encode(_publicGood), // Encode grantee address
value: 0 // No value/ETH
})
})
);
}
}// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; /** * @title Batchable * @author Rafał Kalinowski <[email protected]> * @dev This is BoringBatchable based function with a small twist: because delgatecall passes msg.value * on each call, it may introduce double spending issue. To avoid that, we handle cases when msg.value matters separately. * Please note that you'll have to pass msg.value in amount field for native currency per each call * Additionally, please keep in mind that currently you cannot put payable and nonpayable calls in the same batch - * - nonpayable functions will revert when receiving money */ abstract contract Batchable { uint256 internal _MSG_VALUE; uint256 internal constant _BATCH_NOT_ENTERED = 1; uint256 internal constant _BATCH_ENTERED = 2; uint256 internal _batchStatus; error BatchError(bytes innerError); constructor() { _batchStatus = _BATCH_NOT_ENTERED; } /** * @notice This function allows batched call to self (this contract). * @param _calls An array of inputs for each call. * @dev - it sets _MSG_VALUE variable for a call, if function is payable * check if the function is payable is done in your implementation of function `isMsgValueOverride()` * and _MSG_VALUE is set based on your `calculateMsgValueForACall()` implementation */ // F1: External is ok here because this is the batch function, adding it to a batch makes no sense // F2: Calls in the batch may be payable, delegatecall operates in the same context, so each call in the batch has access to msg.value // C3: The length of the loop is fully under user control, so can't be exploited // C7: Delegatecall is used on the same contract, and there is reentrancy guard in place function batchCall(bytes[] calldata _calls) internal { // bacause we already have reentrancy guard for functions, we set second kind of reentrancy guard require(_batchStatus != _BATCH_ENTERED, "ReentrancyGuard: reentrant call"); uint256 msgValueSentAcc; _batchStatus = _BATCH_ENTERED; for (uint256 i = 0; i < _calls.length; i++) { bool success; bytes memory result; bytes memory data = _calls[i]; bytes4 sig; assembly { sig := mload(add(data, add(0x20, 0))) } // set proper msg.value for payable function, as delegatecall can introduce double spending if (isMsgValueOverride(sig)) { uint256 currentCallPriceAmount = calculateMsgValueForACall(sig, data); _MSG_VALUE = currentCallPriceAmount; msgValueSentAcc += currentCallPriceAmount; require (msgValueSentAcc <= msg.value, "Can't send more than msg.value"); (success, result) = address(this).delegatecall(data); _MSG_VALUE = 0; } else { (success, result) = address(this).delegatecall(data); } if (!success) { _getRevertMsg(result); } } _batchStatus = _BATCH_NOT_ENTERED; } /** * @notice This is part of BoringBatchable contract * https://github.com/boringcrypto/BoringSolidity/blob/master/contracts/BoringBatchable.sol * @dev Helper function to extract a useful revert message from a failed call. * If the returned data is malformed or not correctly abi encoded then this call can fail itself. */ function _getRevertMsg(bytes memory _returnData) internal pure { // If the _res length is less than 68, then // the transaction failed with custom error or silently (without a revert message) if (_returnData.length < 68) revert BatchError(_returnData); assembly { // Slice the sighash. _returnData := add(_returnData, 0x04) } revert(abi.decode(_returnData, (string))); // All that remains is the revert string } /** * @notice Checks if a function is payable, i.e. should _MSG_VALUE be set * @param _selector function selector * @dev Write your logic checking if a function is payable, e.g. this.<function-name>.selector == _selector * WARNING - if you, or someone else if able to construct the same selector for a malicious function (which is not that hard), * the logic may break and the msg.value may be exploited */ function isMsgValueOverride(bytes4 _selector) virtual pure internal returns (bool); /** * @notice Calculates msg.value that should be sent with a call * @param _selector function selector * @param _calldata single call encoded data * @dev You should probably decode function parameters and check what value should be passed */ function calculateMsgValueForACall(bytes4 _selector, bytes memory _calldata) virtual view internal returns (uint256); }
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// A representation of an empty/uninitialized UID.
bytes32 constant EMPTY_UID = 0;
// A zero expiration represents an non-expiring attestation.
uint64 constant NO_EXPIRATION_TIME = 0;
error AccessDenied();
error InvalidEAS();
error InvalidLength();
error InvalidSignature();
error NotFound();
/// @notice A struct representing EIP712 signature data.
struct EIP712Signature {
uint8 v; // The recovery ID.
bytes32 r; // The x-coordinate of the nonce R.
bytes32 s; // The signature data.
}
/// @notice A struct representing a single attestation.
struct Attestation {
bytes32 uid; // A unique identifier of the attestation.
bytes32 schema; // The unique identifier of the schema.
uint64 time; // The time when the attestation was created (Unix timestamp).
uint64 expirationTime; // The time when the attestation expires (Unix timestamp).
uint64 revocationTime; // The time when the attestation was revoked (Unix timestamp).
bytes32 refUID; // The UID of the related attestation.
address recipient; // The recipient of the attestation.
address attester; // The attester/sender of the attestation.
bool revocable; // Whether the attestation is revocable.
bytes data; // Custom attestation data.
}
/// @notice A helper function to work with unchecked iterators in loops.
function uncheckedInc(uint256 i) pure returns (uint256 j) {
unchecked {
j = i + 1;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import { AssetType, FeeType } from "../enums/IDrissEnums.sol";
/**
* @title FeeCalculator
* @author Rafał Kalinowski <[email protected]>
* @notice This is an utility contract for calculating a fee
*/
contract FeeCalculator is Ownable {
AggregatorV3Interface internal immutable MATIC_USD_PRICE_FEED;
uint256 public constant PAYMENT_FEE_SLIPPAGE_PERCENT = 5;
uint256 public PAYMENT_FEE_PERCENTAGE = 10;
uint256 public PAYMENT_FEE_PERCENTAGE_DENOMINATOR = 1000;
uint256 public MINIMAL_PAYMENT_FEE = 1;
uint256 public MINIMAL_PAYMENT_FEE_DENOMINATOR = 1;
// you have to pass your desired fee types in a constructor deriving this contract
mapping (AssetType => FeeType) FEE_TYPE_MAPPING;
constructor(address _maticUsdAggregator) {
require(_maticUsdAggregator != address(0), "Address cannot be 0");
MATIC_USD_PRICE_FEED = AggregatorV3Interface(_maticUsdAggregator);
}
/*
* @notice Get current amount of wei in a dollar
* @dev ChainLink officially supports only USD -> MATIC,
* so we have to convert it back to get current amount of wei in a dollar
*/
function _dollarToWei() internal view returns (uint256) {
(,int256 maticPrice,,,) = MATIC_USD_PRICE_FEED.latestRoundData();
require (maticPrice > 0, "Unable to retrieve MATIC price.");
uint256 maticPriceMultiplier = 10**MATIC_USD_PRICE_FEED.decimals();
return(10**18 * maticPriceMultiplier) / uint256(maticPrice);
}
/**
* @notice Calculates payment fee
* @param _value - payment value
* @param _assetType - asset type, required as ERC20 & ERC721 only take minimal fee
* @return fee - processing fee, few percent of slippage is allowed
*/
function getPaymentFee(uint256 _value, AssetType _assetType) public view returns (uint256) {
uint256 minimumPaymentFee = _getMinimumFee();
uint256 percentageFee = _getPercentageFee(_value);
FeeType feeType = FEE_TYPE_MAPPING[_assetType];
if (feeType == FeeType.Constant) {
return minimumPaymentFee;
} else if (feeType == FeeType.Percentage) {
return percentageFee;
}
// default case - PercentageOrConstantMaximum
if (percentageFee > minimumPaymentFee) return percentageFee; else return minimumPaymentFee;
}
function _getMinimumFee() internal view returns (uint256) {
return (_dollarToWei() * MINIMAL_PAYMENT_FEE) / MINIMAL_PAYMENT_FEE_DENOMINATOR;
}
function _getPercentageFee(uint256 _value) internal view returns (uint256) {
return (_value * PAYMENT_FEE_PERCENTAGE) / PAYMENT_FEE_PERCENTAGE_DENOMINATOR;
}
/**
* @notice Calculates value of a fee from sent msg.value
* @param _valueToSplit - payment value, taken from msg.value
* @param _assetType - asset type, as there may be different calculation logic for each type
* @return fee - processing fee, few percent of slippage is allowed
* @return value - payment value after substracting fee
*/
function _splitPayment(uint256 _valueToSplit, AssetType _assetType) internal view returns (uint256 fee, uint256 value) {
uint256 minimalPaymentFee = _getMinimumFee();
uint256 paymentFee = getPaymentFee(_valueToSplit, _assetType);
// we accept slippage of matic price if fee type is not percentage - it this case we always get % no matter dollar price
if (FEE_TYPE_MAPPING[_assetType] != FeeType.Percentage
&& _valueToSplit >= minimalPaymentFee * (100 - PAYMENT_FEE_SLIPPAGE_PERCENT) / 100
&& _valueToSplit <= minimalPaymentFee) {
fee = _valueToSplit;
} else {
fee = paymentFee;
}
require (_valueToSplit >= fee, "Value sent is smaller than minimal fee.");
value = _valueToSplit - fee;
}
/**
* @notice adjust payment fee percentage for big native currenct transfers
* @dev Solidity is not good when it comes to handling floats. We use denominator then,
* e.g. to set payment fee to 1.5% , just pass paymentFee = 15 & denominator = 1000 => 15 / 1000 = 0.015 = 1.5%
*/
function changePaymentFeePercentage (uint256 _paymentFeePercentage, uint256 _paymentFeeDenominator) external onlyOwner {
require(_paymentFeePercentage > 0, "Payment fee has to be bigger than 0");
require(_paymentFeeDenominator > 0, "Payment fee denominator has to be bigger than 0");
PAYMENT_FEE_PERCENTAGE = _paymentFeePercentage;
PAYMENT_FEE_PERCENTAGE_DENOMINATOR = _paymentFeeDenominator;
}
/**
* @notice adjust minimal payment fee for all asset transfers
* @dev Solidity is not good when it comes to handling floats. We use denominator then,
* e.g. to set minimal payment fee to 2.2$ , just pass paymentFee = 22 & denominator = 10 => 22 / 10 = 2.2
*/
function changeMinimalPaymentFee (uint256 _minimalPaymentFee, uint256 _paymentFeeDenominator) external onlyOwner {
require(_minimalPaymentFee > 0, "Payment fee has to be bigger than 0");
require(_paymentFeeDenominator > 0, "Payment fee denominator has to be bigger than 0");
MINIMAL_PAYMENT_FEE = _minimalPaymentFee;
MINIMAL_PAYMENT_FEE_DENOMINATOR = _paymentFeeDenominator;
}
}// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; /** * @title MultiAssetSender * @author Rafał Kalinowski <[email protected]> * @notice This is an utility contract for sending different kind of assets * @dev Please note that you should make reentrancy check yourself */ contract MultiAssetSender { constructor() { } /** * @notice Wrapper for sending native Coin via call function * @dev When using this function please make sure to not send it to anyone, verify the * address in IDriss registry */ function _sendCoin (address _to, uint256 _amount) internal { (bool sent, ) = payable(_to).call{value: _amount}(""); require(sent, "Failed to send"); } /** * @notice Wrapper for sending single ERC1155 asset * @dev due to how approval in ERC1155 standard is handled, the smart contract has to ask for permissions to manage * ALL tokens "for simplicity"... Hence, it has to be done before calling function that transfers the token * to smart contract, and revoked afterwards */ function _sendERC1155AssetBatch ( uint256[] memory _assetIds, uint256[] memory _amounts, address _from, address _to, address _contractAddress ) internal { IERC1155 nft = IERC1155(_contractAddress); nft.safeBatchTransferFrom(_from, _to, _assetIds, _amounts, ""); } /** * @notice Wrapper for sending multiple ERC1155 assets * @dev due to how approval in ERC1155 standard is handled, the smart contract has to ask for permissions to manage * ALL tokens "for simplicity"... Hence, it has to be done before calling function that transfers the token * to smart contract, and revoked afterwards */ function _sendERC1155Asset ( uint256 _assetId, uint256 _amount, address _from, address _to, address _contractAddress ) internal { IERC1155 nft = IERC1155(_contractAddress); nft.safeTransferFrom(_from, _to, _assetId, _amount, ""); } /** * @notice Wrapper for sending NFT asset */ function _sendNFTAsset ( uint256 _assetIds, address _from, address _to, address _contractAddress ) internal { IERC721 nft = IERC721(_contractAddress); nft.safeTransferFrom(_from, _to, _assetIds, ""); } /** * @notice Wrapper for sending NFT asset with additional checks and iteraton over an array */ function _sendNFTAssetBatch ( uint256[] memory _assetIds, address _from, address _to, address _contractAddress ) internal { require(_assetIds.length > 0, "Nothing to send"); IERC721 nft = IERC721(_contractAddress); for (uint256 i = 0; i < _assetIds.length; ++i) { nft.safeTransferFrom(_from, _to, _assetIds[i], ""); } } /** * @notice Wrapper for sending ERC20 Token asset with additional checks */ function _sendTokenAsset ( uint256 _amount, address _to, address _contractAddress ) internal { IERC20 token = IERC20(_contractAddress); bool sent = token.transfer(_to, _amount); require(sent, "Failed to transfer token"); } /** * @notice Wrapper for sending ERC20 token from specific account with additional checks and iteraton over an array */ function _sendTokenAssetFrom ( uint256 _amount, address _from, address _to, address _contractAddress ) internal { IERC20 token = IERC20(_contractAddress); bool sent = token.transferFrom(_from, _to, _amount); require(sent, "Failed to transfer token"); } }
{
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_nativeUsdAggregator","type":"address"},{"internalType":"address","name":"_eas","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bytes","name":"innerError","type":"bytes"}],"name":"BatchError","type":"error"},{"inputs":[],"name":"InvalidEAS","type":"error"},{"inputs":[],"name":"tipping__withdraw__OnlyAdminCanWithdraw","type":"error"},{"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":"recipientAddress","type":"address"},{"indexed":false,"internalType":"string","name":"message","type":"string"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"TipMessage","type":"event"},{"inputs":[],"name":"MINIMAL_PAYMENT_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINIMAL_PAYMENT_FEE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAYMENT_FEE_PERCENTAGE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAYMENT_FEE_PERCENTAGE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAYMENT_FEE_SLIPPAGE_PERCENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_adminAddress","type":"address"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"publicGoodAddress","type":"address"}],"name":"addPublicGood","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"admins","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"_calls","type":"bytes[]"}],"name":"batch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minimalPaymentFee","type":"uint256"},{"internalType":"uint256","name":"_paymentFeeDenominator","type":"uint256"}],"name":"changeMinimalPaymentFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_paymentFeePercentage","type":"uint256"},{"internalType":"uint256","name":"_paymentFeeDenominator","type":"uint256"}],"name":"changePaymentFeePercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_adminAddress","type":"address"}],"name":"deleteAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"publicGoodAddress","type":"address"}],"name":"deletePublicGood","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"enum AssetType","name":"_assetType","type":"uint8"}],"name":"getPaymentFee","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":"publicGoods","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_assetId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_assetContractAddress","type":"address"},{"internalType":"string","name":"_message","type":"string"}],"name":"sendERC1155To","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_nftContractAddress","type":"address"},{"internalType":"string","name":"_message","type":"string"}],"name":"sendERC721To","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"string","name":"_message","type":"string"}],"name":"sendTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_tokenContractAddr","type":"address"},{"internalType":"string","name":"_message","type":"string"}],"name":"sendTokenTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenContract","type":"address"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c0604052600a6001556103e8600255600160035560016004553480156200002657600080fd5b5060405162003e0238038062003e0283398181016040528101906200004c9190620004f5565b80826200006e62000062620003bf60201b60201c565b620003c760201b60201c565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000e0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000d7906200059d565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff168152505050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200017c576040517f83780ffe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250505060016007819055506001600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506000600560008060038111156200022d576200022c620005bf565b5b6003811115620002425762000241620005bf565b5b815260200190815260200160002060006101000a81548160ff02191690836002811115620002755762000274620005bf565b5b021790555060006005600060016003811115620002975762000296620005bf565b5b6003811115620002ac57620002ab620005bf565b5b815260200190815260200160002060006101000a81548160ff02191690836002811115620002df57620002de620005bf565b5b021790555060026005600060026003811115620003015762000300620005bf565b5b6003811115620003165762000315620005bf565b5b815260200190815260200160002060006101000a81548160ff02191690836002811115620003495762000348620005bf565b5b02179055506002600560006003808111156200036a5762000369620005bf565b5b60038111156200037f576200037e620005bf565b5b815260200190815260200160002060006101000a81548160ff02191690836002811115620003b257620003b1620005bf565b5b02179055505050620005ee565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620004bd8262000490565b9050919050565b620004cf81620004b0565b8114620004db57600080fd5b50565b600081519050620004ef81620004c4565b92915050565b600080604083850312156200050f576200050e6200048b565b5b60006200051f85828601620004de565b92505060206200053285828601620004de565b9150509250929050565b600082825260208201905092915050565b7f416464726573732063616e6e6f74206265203000000000000000000000000000600082015250565b6000620005856013836200053c565b915062000592826200054d565b602082019050919050565b60006020820190508181036000830152620005b88162000576565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60805160a0516137e76200061b60003960006113d2015260008181611efe0152611fd801526137e76000f3fe6080604052600436106101815760003560e01c806370480275116100d1578063894760691161008a5780639cd6aa4c116100645780639cd6aa4c146104ef578063b20d0bff1461052c578063ce606ee014610555578063f2fde38b1461058057610181565b8063894760691461047f5780638d157db8146104a85780638da5cb5b146104c457610181565b806370480275146103925780637129607a146103bb578063715018a6146103d757806380fa375f146103ee578063823130321461041757806383a4c7e11461045457610181565b806327cb0ba11161013e57806341dfeca51161011857806341dfeca5146102e5578063429b62e5146103015780635c73f1631461033e5780635cfdb0861461036957610181565b806327cb0ba11461027a57806327e1f7df146102a55780633ccfd60b146102ce57610181565b806301ffc9a71461018657806303f613dc146101c35780630728c7d2146101ee5780630f7f630a1461021757806316e49145146102425780631e897afb1461025e575b600080fd5b34801561019257600080fd5b506101ad60048036038101906101a89190612105565b6105a9565b6040516101ba919061214d565b60405180910390f35b3480156101cf57600080fd5b506101d861067b565b6040516101e59190612181565b60405180910390f35b3480156101fa57600080fd5b50610215600480360381019061021091906121c8565b610681565b005b34801561022357600080fd5b5061022c610721565b6040516102399190612181565b60405180910390f35b61025c600480360381019061025791906123ac565b610727565b005b6102786004803603810190610273919061247b565b610849565b005b34801561028657600080fd5b5061028f610857565b60405161029c9190612181565b60405180910390f35b3480156102b157600080fd5b506102cc60048036038101906102c791906124c8565b61085d565b005b3480156102da57600080fd5b506102e36108c0565b005b6102ff60048036038101906102fa91906124f5565b6109f9565b005b34801561030d57600080fd5b50610328600480360381019061032391906124c8565b610b10565b604051610335919061214d565b60405180910390f35b34801561034a57600080fd5b50610353610b30565b6040516103609190612181565b60405180910390f35b34801561037557600080fd5b50610390600480360381019061038b91906124c8565b610b36565b005b34801561039e57600080fd5b506103b960048036038101906103b491906124c8565b610b99565b005b6103d560048036038101906103d09190612578565b610bfc565b005b3480156103e357600080fd5b506103ec610cb7565b005b3480156103fa57600080fd5b50610415600480360381019061041091906121c8565b610cfa565b005b34801561042357600080fd5b5061043e600480360381019061043991906124c8565b610d9a565b60405161044b919061214d565b60405180910390f35b34801561046057600080fd5b50610469610dba565b6040516104769190612181565b60405180910390f35b34801561048b57600080fd5b506104a660048036038101906104a191906124c8565b610dbf565b005b6104c260048036038101906104bd91906124f5565b610f4a565b005b3480156104d057600080fd5b506104d9611003565b6040516104e6919061261e565b60405180910390f35b3480156104fb57600080fd5b506105166004803603810190610511919061265e565b61102c565b6040516105239190612181565b60405180910390f35b34801561053857600080fd5b50610553600480360381019061054e91906124c8565b61111c565b005b34801561056157600080fd5b5061056a611176565b604051610577919061261e565b60405180910390f35b34801561058c57600080fd5b506105a760048036038101906105a291906124c8565b61119c565b005b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061067457507f492623ea000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60025481565b61068961121f565b600082116106cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c390612721565b60405180910390fd5b6000811161070f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610706906127b3565b60405180910390fd5b81600181905550806002819055505050565b60035481565b60008060065411610738573461073c565b6006545b9050600061074b82600061129d565b915050600a60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156107ae578190506107ac856113ce565b505b6107b8858261151d565b600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167ff9c3f5954c862ec34206d922a3ca6e4a688423fe63e3ae49147f33ae54ba293f86858761082c9190612802565b60405161083a9291906128a4565b60405180910390a45050505050565b61085382826115ce565b5050565b60045481565b61086561121f565b6000600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60011515600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151461094a576040517f3db4b39200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003373ffffffffffffffffffffffffffffffffffffffff164760405161097090612905565b60006040518083038185875af1925050503d80600081146109ad576040519150601f19603f3d011682016040523d82523d6000602084013e6109b2565b606091505b50509050806109f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ed90612966565b60405180910390fd5b50565b6000610a0684600161129d565b915050600a60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610a6957839050610a67856113ce565b505b610a7584333086611839565b610a8081868561190a565b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167ff9c3f5954c862ec34206d922a3ca6e4a688423fe63e3ae49147f33ae54ba293f858589610af39190612802565b604051610b019291906128a4565b60405180910390a45050505050565b60096020528060005260406000206000915054906101000a900460ff1681565b60015481565b610b3e61121f565b6001600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b610ba161121f565b6001600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60008060065411610c0d5734610c11565b6006545b90506000610c2082600361129d565b509050610c308686338a886119d8565b8373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167ff9c3f5954c862ec34206d922a3ca6e4a688423fe63e3ae49147f33ae54ba293f8685604051610ca69291906128a4565b60405180910390a450505050505050565b610cbf61121f565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cf1906129d2565b60405180910390fd5b610d0261121f565b60008211610d45576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3c90612721565b60405180910390fd5b60008111610d88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7f906127b3565b60405180910390fd5b81600381905550806004819055505050565b600a6020528060005260406000206000915054906101000a900460ff1681565b600581565b60011515600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610e49576040517f3db4b39200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008190508073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb338373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610ea4919061261e565b602060405180830381865afa158015610ec1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee59190612a07565b6040518363ffffffff1660e01b8152600401610f02929190612a34565b6020604051808303816000875af1158015610f21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f459190612a89565b505050565b60008060065411610f5b5734610f5f565b6006545b90506000610f6e82600261129d565b509050610f7d85338887611a56565b8373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167ff9c3f5954c862ec34206d922a3ca6e4a688423fe63e3ae49147f33ae54ba293f8685604051610ff39291906128a4565b60405180910390a4505050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611037611ad1565b9050600061104485611afa565b905060006005600086600381111561105f5761105e612ab6565b5b600381111561107157611070612ab6565b5b815260200190815260200160002060009054906101000a900460ff1690506002808111156110a2576110a1612ab6565b5b8160028111156110b5576110b4612ab6565b5b036110c557829350505050611116565b600060028111156110d9576110d8612ab6565b5b8160028111156110ec576110eb612ab6565b5b036110fc57819350505050611116565b8282111561110f57819350505050611116565b8293505050505b92915050565b61112461121f565b600a60008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff021916905550565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6111a461121f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611213576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120a90612b57565b60405180910390fd5b61121c81611b1e565b50565b611227611be2565b73ffffffffffffffffffffffffffffffffffffffff16611245611003565b73ffffffffffffffffffffffffffffffffffffffff161461129b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129290612bc3565b60405180910390fd5b565b60008060006112aa611ad1565b905060006112b8868661102c565b9050600060028111156112ce576112cd612ab6565b5b600560008760038111156112e5576112e4612ab6565b5b60038111156112f7576112f6612ab6565b5b815260200190815260200160002060009054906101000a900460ff16600281111561132557611324612ab6565b5b14158015611357575060646005606461133e9190612802565b836113499190612be3565b6113539190612c54565b8610155b80156113635750818611155b1561137057859350611374565b8093505b838610156113b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113ae90612cf7565b60405180910390fd5b83866113c39190612802565b925050509250929050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f17325e760405180604001604052807f28b73429cc730191053ba7fe21e17253be25dbab480f0c3a369de5217657d92560001b81526020016040518060c001604052803373ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581526020016000801b81526020018760405160200161149b919061261e565b604051602081830303815290604052815260200160008152508152506040518263ffffffff1660e01b81526004016114d39190612e9b565b6020604051808303816000875af11580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115169190612ee9565b9050919050565b60008273ffffffffffffffffffffffffffffffffffffffff168260405161154390612905565b60006040518083038185875af1925050503d8060008114611580576040519150601f19603f3d011682016040523d82523d6000602084013e611585565b606091505b50509050806115c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115c090612f62565b60405180910390fd5b505050565b600260075403611613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161160a90612fce565b60405180910390fd5b6000600260078190555060005b8383905081101561182b5760006060600086868581811061164457611643612fee565b5b9050602002810190611656919061302c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050905060008060200182015190506116af81611bea565b156117965760006116c08284611d28565b90508060068190555080876116d5919061308f565b96503487111561171a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117119061310f565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168360405161173f9190613160565b600060405180830381855af49150503d806000811461177a576040519150601f19603f3d011682016040523d82523d6000602084013e61177f565b606091505b508095508196505050600060068190555050611805565b3073ffffffffffffffffffffffffffffffffffffffff16826040516117bb9190613160565b600060405180830381855af49150503d80600081146117f6576040519150601f19603f3d011682016040523d82523d6000602084013e6117fb565b606091505b5080945081955050505b836118145761181383611e5c565b5b50505050808061182390613177565b915050611620565b506001600781905550505050565b600081905060008173ffffffffffffffffffffffffffffffffffffffff166323b872dd8686896040518463ffffffff1660e01b815260040161187d939291906131bf565b6020604051808303816000875af115801561189c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c09190612a89565b905080611902576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118f990613242565b60405180910390fd5b505050505050565b600081905060008173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85876040518363ffffffff1660e01b815260040161194c929190612a34565b6020604051808303816000875af115801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190612a89565b9050806119d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119c890613242565b60405180910390fd5b5050505050565b60008190508073ffffffffffffffffffffffffffffffffffffffff1663f242432a858589896040518563ffffffff1660e01b8152600401611a1c9493929190613296565b600060405180830381600087803b158015611a3657600080fd5b505af1158015611a4a573d6000803e3d6000fd5b50505050505050505050565b60008190508073ffffffffffffffffffffffffffffffffffffffff1663b88d4fde8585886040518463ffffffff1660e01b8152600401611a98939291906132ee565b600060405180830381600087803b158015611ab257600080fd5b505af1158015611ac6573d6000803e3d6000fd5b505050505050505050565b6000600454600354611ae1611ef9565b611aeb9190612be3565b611af59190612c54565b905090565b600060025460015483611b0d9190612be3565b611b179190612c54565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600033905090565b60006316e4914560e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611c8357506341dfeca560e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611cd25750638d157db860e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611d215750637129607a60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b6000806316e4914560e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603611d835760448301519050611e52565b6341dfeca560e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603611de257611ddb6000600161102c565b9050611e51565b6341dfeca560e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603611e4157611e3a6000600261102c565b9050611e50565b611e4d6000600361102c565b90505b5b5b8091505092915050565b604481511015611ea357806040517fd9354485000000000000000000000000000000000000000000000000000000008152600401611e9a9190613371565b60405180910390fd5b60048101905080806020019051810190611ebd9190613403565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ef0919061344c565b60405180910390fd5b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015611f67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8b91906134e6565b50505091505060008113611fd4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fcb906135ad565b60405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612041573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120659190613606565b600a6120719190613766565b90508181670de0b6b3a76400006120889190612be3565b6120929190612c54565b9250505090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6120e2816120ad565b81146120ed57600080fd5b50565b6000813590506120ff816120d9565b92915050565b60006020828403121561211b5761211a6120a3565b5b6000612129848285016120f0565b91505092915050565b60008115159050919050565b61214781612132565b82525050565b6000602082019050612162600083018461213e565b92915050565b6000819050919050565b61217b81612168565b82525050565b60006020820190506121966000830184612172565b92915050565b6121a581612168565b81146121b057600080fd5b50565b6000813590506121c28161219c565b92915050565b600080604083850312156121df576121de6120a3565b5b60006121ed858286016121b3565b92505060206121fe858286016121b3565b9150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061223382612208565b9050919050565b61224381612228565b811461224e57600080fd5b50565b6000813590506122608161223a565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6122b982612270565b810181811067ffffffffffffffff821117156122d8576122d7612281565b5b80604052505050565b60006122eb612099565b90506122f782826122b0565b919050565b600067ffffffffffffffff82111561231757612316612281565b5b61232082612270565b9050602081019050919050565b82818337600083830152505050565b600061234f61234a846122fc565b6122e1565b90508281526020810184848401111561236b5761236a61226b565b5b61237684828561232d565b509392505050565b600082601f83011261239357612392612266565b5b81356123a384826020860161233c565b91505092915050565b6000806000606084860312156123c5576123c46120a3565b5b60006123d386828701612251565b93505060206123e4868287016121b3565b925050604084013567ffffffffffffffff811115612405576124046120a8565b5b6124118682870161237e565b9150509250925092565b600080fd5b600080fd5b60008083601f84011261243b5761243a612266565b5b8235905067ffffffffffffffff8111156124585761245761241b565b5b60208301915083602082028301111561247457612473612420565b5b9250929050565b60008060208385031215612492576124916120a3565b5b600083013567ffffffffffffffff8111156124b0576124af6120a8565b5b6124bc85828601612425565b92509250509250929050565b6000602082840312156124de576124dd6120a3565b5b60006124ec84828501612251565b91505092915050565b6000806000806080858703121561250f5761250e6120a3565b5b600061251d87828801612251565b945050602061252e878288016121b3565b935050604061253f87828801612251565b925050606085013567ffffffffffffffff8111156125605761255f6120a8565b5b61256c8782880161237e565b91505092959194509250565b600080600080600060a08688031215612594576125936120a3565b5b60006125a288828901612251565b95505060206125b3888289016121b3565b94505060406125c4888289016121b3565b93505060606125d588828901612251565b925050608086013567ffffffffffffffff8111156125f6576125f56120a8565b5b6126028882890161237e565b9150509295509295909350565b61261881612228565b82525050565b6000602082019050612633600083018461260f565b92915050565b6004811061264657600080fd5b50565b60008135905061265881612639565b92915050565b60008060408385031215612675576126746120a3565b5b6000612683858286016121b3565b925050602061269485828601612649565b9150509250929050565b600082825260208201905092915050565b7f5061796d656e74206665652068617320746f206265206269676765722074686160008201527f6e20300000000000000000000000000000000000000000000000000000000000602082015250565b600061270b60238361269e565b9150612716826126af565b604082019050919050565b6000602082019050818103600083015261273a816126fe565b9050919050565b7f5061796d656e74206665652064656e6f6d696e61746f722068617320746f206260008201527f6520626967676572207468616e20300000000000000000000000000000000000602082015250565b600061279d602f8361269e565b91506127a882612741565b604082019050919050565b600060208201905081810360008301526127cc81612790565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061280d82612168565b915061281883612168565b92508282039050818111156128305761282f6127d3565b5b92915050565b600081519050919050565b60005b8381101561285f578082015181840152602081019050612844565b60008484015250505050565b600061287682612836565b612880818561269e565b9350612890818560208601612841565b61289981612270565b840191505092915050565b600060408201905081810360008301526128be818561286b565b90506128cd6020830184612172565b9392505050565b600081905092915050565b50565b60006128ef6000836128d4565b91506128fa826128df565b600082019050919050565b6000612910826128e2565b9150819050919050565b7f4661696c656420746f2077697468647261772e00000000000000000000000000600082015250565b600061295060138361269e565b915061295b8261291a565b602082019050919050565b6000602082019050818103600083015261297f81612943565b9050919050565b7f4f7065726174696f6e206e6f7420737570706f72746564000000000000000000600082015250565b60006129bc60178361269e565b91506129c782612986565b602082019050919050565b600060208201905081810360008301526129eb816129af565b9050919050565b600081519050612a018161219c565b92915050565b600060208284031215612a1d57612a1c6120a3565b5b6000612a2b848285016129f2565b91505092915050565b6000604082019050612a49600083018561260f565b612a566020830184612172565b9392505050565b612a6681612132565b8114612a7157600080fd5b50565b600081519050612a8381612a5d565b92915050565b600060208284031215612a9f57612a9e6120a3565b5b6000612aad84828501612a74565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000612b4160268361269e565b9150612b4c82612ae5565b604082019050919050565b60006020820190508181036000830152612b7081612b34565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000612bad60208361269e565b9150612bb882612b77565b602082019050919050565b60006020820190508181036000830152612bdc81612ba0565b9050919050565b6000612bee82612168565b9150612bf983612168565b9250828202612c0781612168565b91508282048414831517612c1e57612c1d6127d3565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000612c5f82612168565b9150612c6a83612168565b925082612c7a57612c79612c25565b5b828204905092915050565b7f56616c75652073656e7420697320736d616c6c6572207468616e206d696e696d60008201527f616c206665652e00000000000000000000000000000000000000000000000000602082015250565b6000612ce160278361269e565b9150612cec82612c85565b604082019050919050565b60006020820190508181036000830152612d1081612cd4565b9050919050565b6000819050919050565b612d2a81612d17565b82525050565b612d3981612228565b82525050565b600067ffffffffffffffff82169050919050565b612d5c81612d3f565b82525050565b612d6b81612132565b82525050565b600081519050919050565b600082825260208201905092915050565b6000612d9882612d71565b612da28185612d7c565b9350612db2818560208601612841565b612dbb81612270565b840191505092915050565b612dcf81612168565b82525050565b600060c083016000830151612ded6000860182612d30565b506020830151612e006020860182612d53565b506040830151612e136040860182612d62565b506060830151612e266060860182612d21565b5060808301518482036080860152612e3e8282612d8d565b91505060a0830151612e5360a0860182612dc6565b508091505092915050565b6000604083016000830151612e766000860182612d21565b5060208301518482036020860152612e8e8282612dd5565b9150508091505092915050565b60006020820190508181036000830152612eb58184612e5e565b905092915050565b612ec681612d17565b8114612ed157600080fd5b50565b600081519050612ee381612ebd565b92915050565b600060208284031215612eff57612efe6120a3565b5b6000612f0d84828501612ed4565b91505092915050565b7f4661696c656420746f2073656e64000000000000000000000000000000000000600082015250565b6000612f4c600e8361269e565b9150612f5782612f16565b602082019050919050565b60006020820190508181036000830152612f7b81612f3f565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000612fb8601f8361269e565b9150612fc382612f82565b602082019050919050565b60006020820190508181036000830152612fe781612fab565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126130495761304861301d565b5b80840192508235915067ffffffffffffffff82111561306b5761306a613022565b5b60208301925060018202360383131561308757613086613027565b5b509250929050565b600061309a82612168565b91506130a583612168565b92508282019050808211156130bd576130bc6127d3565b5b92915050565b7f43616e27742073656e64206d6f7265207468616e206d73672e76616c75650000600082015250565b60006130f9601e8361269e565b9150613104826130c3565b602082019050919050565b60006020820190508181036000830152613128816130ec565b9050919050565b600061313a82612d71565b61314481856128d4565b9350613154818560208601612841565b80840191505092915050565b600061316c828461312f565b915081905092915050565b600061318282612168565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036131b4576131b36127d3565b5b600182019050919050565b60006060820190506131d4600083018661260f565b6131e1602083018561260f565b6131ee6040830184612172565b949350505050565b7f4661696c656420746f207472616e7366657220746f6b656e0000000000000000600082015250565b600061322c60188361269e565b9150613237826131f6565b602082019050919050565b6000602082019050818103600083015261325b8161321f565b9050919050565b600082825260208201905092915050565b6000613280600083613262565b915061328b826128df565b600082019050919050565b600060a0820190506132ab600083018761260f565b6132b8602083018661260f565b6132c56040830185612172565b6132d26060830184612172565b81810360808301526132e381613273565b905095945050505050565b6000608082019050613303600083018661260f565b613310602083018561260f565b61331d6040830184612172565b818103606083015261332e81613273565b9050949350505050565b600061334382612d71565b61334d8185613262565b935061335d818560208601612841565b61336681612270565b840191505092915050565b6000602082019050818103600083015261338b8184613338565b905092915050565b60006133a66133a1846122fc565b6122e1565b9050828152602081018484840111156133c2576133c161226b565b5b6133cd848285612841565b509392505050565b600082601f8301126133ea576133e9612266565b5b81516133fa848260208601613393565b91505092915050565b600060208284031215613419576134186120a3565b5b600082015167ffffffffffffffff811115613437576134366120a8565b5b613443848285016133d5565b91505092915050565b60006020820190508181036000830152613466818461286b565b905092915050565b600069ffffffffffffffffffff82169050919050565b61348d8161346e565b811461349857600080fd5b50565b6000815190506134aa81613484565b92915050565b6000819050919050565b6134c3816134b0565b81146134ce57600080fd5b50565b6000815190506134e0816134ba565b92915050565b600080600080600060a08688031215613502576135016120a3565b5b60006135108882890161349b565b9550506020613521888289016134d1565b9450506040613532888289016129f2565b9350506060613543888289016129f2565b92505060806135548882890161349b565b9150509295509295909350565b7f556e61626c6520746f207265747269657665204d415449432070726963652e00600082015250565b6000613597601f8361269e565b91506135a282613561565b602082019050919050565b600060208201905081810360008301526135c68161358a565b9050919050565b600060ff82169050919050565b6135e3816135cd565b81146135ee57600080fd5b50565b600081519050613600816135da565b92915050565b60006020828403121561361c5761361b6120a3565b5b600061362a848285016135f1565b91505092915050565b60008160011c9050919050565b6000808291508390505b600185111561368a57808604811115613666576136656127d3565b5b60018516156136755780820291505b808102905061368385613633565b945061364a565b94509492505050565b6000826136a3576001905061375f565b816136b1576000905061375f565b81600181146136c757600281146136d157613700565b600191505061375f565b60ff8411156136e3576136e26127d3565b5b8360020a9150848211156136fa576136f96127d3565b5b5061375f565b5060208310610133831016604e8410600b84101617156137355782820a9050838111156137305761372f6127d3565b5b61375f565b6137428484846001613640565b92509050818404811115613759576137586127d3565b5b81810290505b9392505050565b600061377182612168565b915061377c836135cd565b92506137a97fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484613693565b90509291505056fea264697066735822122013d83d2ed742d0e6368e6d5c8b4378652da5bb3ef11c058842b6e287f5eae11164736f6c6343000811003300000000000000000000000013e3ee699d1909e989722e753853ae30b17e08c50000000000000000000000004200000000000000000000000000000000000021
Deployed Bytecode
0x6080604052600436106101815760003560e01c806370480275116100d1578063894760691161008a5780639cd6aa4c116100645780639cd6aa4c146104ef578063b20d0bff1461052c578063ce606ee014610555578063f2fde38b1461058057610181565b8063894760691461047f5780638d157db8146104a85780638da5cb5b146104c457610181565b806370480275146103925780637129607a146103bb578063715018a6146103d757806380fa375f146103ee578063823130321461041757806383a4c7e11461045457610181565b806327cb0ba11161013e57806341dfeca51161011857806341dfeca5146102e5578063429b62e5146103015780635c73f1631461033e5780635cfdb0861461036957610181565b806327cb0ba11461027a57806327e1f7df146102a55780633ccfd60b146102ce57610181565b806301ffc9a71461018657806303f613dc146101c35780630728c7d2146101ee5780630f7f630a1461021757806316e49145146102425780631e897afb1461025e575b600080fd5b34801561019257600080fd5b506101ad60048036038101906101a89190612105565b6105a9565b6040516101ba919061214d565b60405180910390f35b3480156101cf57600080fd5b506101d861067b565b6040516101e59190612181565b60405180910390f35b3480156101fa57600080fd5b50610215600480360381019061021091906121c8565b610681565b005b34801561022357600080fd5b5061022c610721565b6040516102399190612181565b60405180910390f35b61025c600480360381019061025791906123ac565b610727565b005b6102786004803603810190610273919061247b565b610849565b005b34801561028657600080fd5b5061028f610857565b60405161029c9190612181565b60405180910390f35b3480156102b157600080fd5b506102cc60048036038101906102c791906124c8565b61085d565b005b3480156102da57600080fd5b506102e36108c0565b005b6102ff60048036038101906102fa91906124f5565b6109f9565b005b34801561030d57600080fd5b50610328600480360381019061032391906124c8565b610b10565b604051610335919061214d565b60405180910390f35b34801561034a57600080fd5b50610353610b30565b6040516103609190612181565b60405180910390f35b34801561037557600080fd5b50610390600480360381019061038b91906124c8565b610b36565b005b34801561039e57600080fd5b506103b960048036038101906103b491906124c8565b610b99565b005b6103d560048036038101906103d09190612578565b610bfc565b005b3480156103e357600080fd5b506103ec610cb7565b005b3480156103fa57600080fd5b50610415600480360381019061041091906121c8565b610cfa565b005b34801561042357600080fd5b5061043e600480360381019061043991906124c8565b610d9a565b60405161044b919061214d565b60405180910390f35b34801561046057600080fd5b50610469610dba565b6040516104769190612181565b60405180910390f35b34801561048b57600080fd5b506104a660048036038101906104a191906124c8565b610dbf565b005b6104c260048036038101906104bd91906124f5565b610f4a565b005b3480156104d057600080fd5b506104d9611003565b6040516104e6919061261e565b60405180910390f35b3480156104fb57600080fd5b506105166004803603810190610511919061265e565b61102c565b6040516105239190612181565b60405180910390f35b34801561053857600080fd5b50610553600480360381019061054e91906124c8565b61111c565b005b34801561056157600080fd5b5061056a611176565b604051610577919061261e565b60405180910390f35b34801561058c57600080fd5b506105a760048036038101906105a291906124c8565b61119c565b005b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061067457507f492623ea000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60025481565b61068961121f565b600082116106cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c390612721565b60405180910390fd5b6000811161070f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610706906127b3565b60405180910390fd5b81600181905550806002819055505050565b60035481565b60008060065411610738573461073c565b6006545b9050600061074b82600061129d565b915050600a60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156107ae578190506107ac856113ce565b505b6107b8858261151d565b600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167ff9c3f5954c862ec34206d922a3ca6e4a688423fe63e3ae49147f33ae54ba293f86858761082c9190612802565b60405161083a9291906128a4565b60405180910390a45050505050565b61085382826115ce565b5050565b60045481565b61086561121f565b6000600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60011515600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151461094a576040517f3db4b39200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003373ffffffffffffffffffffffffffffffffffffffff164760405161097090612905565b60006040518083038185875af1925050503d80600081146109ad576040519150601f19603f3d011682016040523d82523d6000602084013e6109b2565b606091505b50509050806109f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ed90612966565b60405180910390fd5b50565b6000610a0684600161129d565b915050600a60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610a6957839050610a67856113ce565b505b610a7584333086611839565b610a8081868561190a565b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167ff9c3f5954c862ec34206d922a3ca6e4a688423fe63e3ae49147f33ae54ba293f858589610af39190612802565b604051610b019291906128a4565b60405180910390a45050505050565b60096020528060005260406000206000915054906101000a900460ff1681565b60015481565b610b3e61121f565b6001600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b610ba161121f565b6001600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60008060065411610c0d5734610c11565b6006545b90506000610c2082600361129d565b509050610c308686338a886119d8565b8373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167ff9c3f5954c862ec34206d922a3ca6e4a688423fe63e3ae49147f33ae54ba293f8685604051610ca69291906128a4565b60405180910390a450505050505050565b610cbf61121f565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cf1906129d2565b60405180910390fd5b610d0261121f565b60008211610d45576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3c90612721565b60405180910390fd5b60008111610d88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7f906127b3565b60405180910390fd5b81600381905550806004819055505050565b600a6020528060005260406000206000915054906101000a900460ff1681565b600581565b60011515600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610e49576040517f3db4b39200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008190508073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb338373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610ea4919061261e565b602060405180830381865afa158015610ec1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee59190612a07565b6040518363ffffffff1660e01b8152600401610f02929190612a34565b6020604051808303816000875af1158015610f21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f459190612a89565b505050565b60008060065411610f5b5734610f5f565b6006545b90506000610f6e82600261129d565b509050610f7d85338887611a56565b8373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167ff9c3f5954c862ec34206d922a3ca6e4a688423fe63e3ae49147f33ae54ba293f8685604051610ff39291906128a4565b60405180910390a4505050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611037611ad1565b9050600061104485611afa565b905060006005600086600381111561105f5761105e612ab6565b5b600381111561107157611070612ab6565b5b815260200190815260200160002060009054906101000a900460ff1690506002808111156110a2576110a1612ab6565b5b8160028111156110b5576110b4612ab6565b5b036110c557829350505050611116565b600060028111156110d9576110d8612ab6565b5b8160028111156110ec576110eb612ab6565b5b036110fc57819350505050611116565b8282111561110f57819350505050611116565b8293505050505b92915050565b61112461121f565b600a60008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff021916905550565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6111a461121f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611213576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120a90612b57565b60405180910390fd5b61121c81611b1e565b50565b611227611be2565b73ffffffffffffffffffffffffffffffffffffffff16611245611003565b73ffffffffffffffffffffffffffffffffffffffff161461129b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129290612bc3565b60405180910390fd5b565b60008060006112aa611ad1565b905060006112b8868661102c565b9050600060028111156112ce576112cd612ab6565b5b600560008760038111156112e5576112e4612ab6565b5b60038111156112f7576112f6612ab6565b5b815260200190815260200160002060009054906101000a900460ff16600281111561132557611324612ab6565b5b14158015611357575060646005606461133e9190612802565b836113499190612be3565b6113539190612c54565b8610155b80156113635750818611155b1561137057859350611374565b8093505b838610156113b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113ae90612cf7565b60405180910390fd5b83866113c39190612802565b925050509250929050565b60007f000000000000000000000000420000000000000000000000000000000000002173ffffffffffffffffffffffffffffffffffffffff1663f17325e760405180604001604052807f28b73429cc730191053ba7fe21e17253be25dbab480f0c3a369de5217657d92560001b81526020016040518060c001604052803373ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581526020016000801b81526020018760405160200161149b919061261e565b604051602081830303815290604052815260200160008152508152506040518263ffffffff1660e01b81526004016114d39190612e9b565b6020604051808303816000875af11580156114f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115169190612ee9565b9050919050565b60008273ffffffffffffffffffffffffffffffffffffffff168260405161154390612905565b60006040518083038185875af1925050503d8060008114611580576040519150601f19603f3d011682016040523d82523d6000602084013e611585565b606091505b50509050806115c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115c090612f62565b60405180910390fd5b505050565b600260075403611613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161160a90612fce565b60405180910390fd5b6000600260078190555060005b8383905081101561182b5760006060600086868581811061164457611643612fee565b5b9050602002810190611656919061302c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050905060008060200182015190506116af81611bea565b156117965760006116c08284611d28565b90508060068190555080876116d5919061308f565b96503487111561171a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117119061310f565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168360405161173f9190613160565b600060405180830381855af49150503d806000811461177a576040519150601f19603f3d011682016040523d82523d6000602084013e61177f565b606091505b508095508196505050600060068190555050611805565b3073ffffffffffffffffffffffffffffffffffffffff16826040516117bb9190613160565b600060405180830381855af49150503d80600081146117f6576040519150601f19603f3d011682016040523d82523d6000602084013e6117fb565b606091505b5080945081955050505b836118145761181383611e5c565b5b50505050808061182390613177565b915050611620565b506001600781905550505050565b600081905060008173ffffffffffffffffffffffffffffffffffffffff166323b872dd8686896040518463ffffffff1660e01b815260040161187d939291906131bf565b6020604051808303816000875af115801561189c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c09190612a89565b905080611902576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118f990613242565b60405180910390fd5b505050505050565b600081905060008173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85876040518363ffffffff1660e01b815260040161194c929190612a34565b6020604051808303816000875af115801561196b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198f9190612a89565b9050806119d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119c890613242565b60405180910390fd5b5050505050565b60008190508073ffffffffffffffffffffffffffffffffffffffff1663f242432a858589896040518563ffffffff1660e01b8152600401611a1c9493929190613296565b600060405180830381600087803b158015611a3657600080fd5b505af1158015611a4a573d6000803e3d6000fd5b50505050505050505050565b60008190508073ffffffffffffffffffffffffffffffffffffffff1663b88d4fde8585886040518463ffffffff1660e01b8152600401611a98939291906132ee565b600060405180830381600087803b158015611ab257600080fd5b505af1158015611ac6573d6000803e3d6000fd5b505050505050505050565b6000600454600354611ae1611ef9565b611aeb9190612be3565b611af59190612c54565b905090565b600060025460015483611b0d9190612be3565b611b179190612c54565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600033905090565b60006316e4914560e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611c8357506341dfeca560e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611cd25750638d157db860e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611d215750637129607a60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b6000806316e4914560e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603611d835760448301519050611e52565b6341dfeca560e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603611de257611ddb6000600161102c565b9050611e51565b6341dfeca560e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603611e4157611e3a6000600261102c565b9050611e50565b611e4d6000600361102c565b90505b5b5b8091505092915050565b604481511015611ea357806040517fd9354485000000000000000000000000000000000000000000000000000000008152600401611e9a9190613371565b60405180910390fd5b60048101905080806020019051810190611ebd9190613403565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ef0919061344c565b60405180910390fd5b6000807f00000000000000000000000013e3ee699d1909e989722e753853ae30b17e08c573ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015611f67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8b91906134e6565b50505091505060008113611fd4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fcb906135ad565b60405180910390fd5b60007f00000000000000000000000013e3ee699d1909e989722e753853ae30b17e08c573ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612041573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120659190613606565b600a6120719190613766565b90508181670de0b6b3a76400006120889190612be3565b6120929190612c54565b9250505090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6120e2816120ad565b81146120ed57600080fd5b50565b6000813590506120ff816120d9565b92915050565b60006020828403121561211b5761211a6120a3565b5b6000612129848285016120f0565b91505092915050565b60008115159050919050565b61214781612132565b82525050565b6000602082019050612162600083018461213e565b92915050565b6000819050919050565b61217b81612168565b82525050565b60006020820190506121966000830184612172565b92915050565b6121a581612168565b81146121b057600080fd5b50565b6000813590506121c28161219c565b92915050565b600080604083850312156121df576121de6120a3565b5b60006121ed858286016121b3565b92505060206121fe858286016121b3565b9150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061223382612208565b9050919050565b61224381612228565b811461224e57600080fd5b50565b6000813590506122608161223a565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6122b982612270565b810181811067ffffffffffffffff821117156122d8576122d7612281565b5b80604052505050565b60006122eb612099565b90506122f782826122b0565b919050565b600067ffffffffffffffff82111561231757612316612281565b5b61232082612270565b9050602081019050919050565b82818337600083830152505050565b600061234f61234a846122fc565b6122e1565b90508281526020810184848401111561236b5761236a61226b565b5b61237684828561232d565b509392505050565b600082601f83011261239357612392612266565b5b81356123a384826020860161233c565b91505092915050565b6000806000606084860312156123c5576123c46120a3565b5b60006123d386828701612251565b93505060206123e4868287016121b3565b925050604084013567ffffffffffffffff811115612405576124046120a8565b5b6124118682870161237e565b9150509250925092565b600080fd5b600080fd5b60008083601f84011261243b5761243a612266565b5b8235905067ffffffffffffffff8111156124585761245761241b565b5b60208301915083602082028301111561247457612473612420565b5b9250929050565b60008060208385031215612492576124916120a3565b5b600083013567ffffffffffffffff8111156124b0576124af6120a8565b5b6124bc85828601612425565b92509250509250929050565b6000602082840312156124de576124dd6120a3565b5b60006124ec84828501612251565b91505092915050565b6000806000806080858703121561250f5761250e6120a3565b5b600061251d87828801612251565b945050602061252e878288016121b3565b935050604061253f87828801612251565b925050606085013567ffffffffffffffff8111156125605761255f6120a8565b5b61256c8782880161237e565b91505092959194509250565b600080600080600060a08688031215612594576125936120a3565b5b60006125a288828901612251565b95505060206125b3888289016121b3565b94505060406125c4888289016121b3565b93505060606125d588828901612251565b925050608086013567ffffffffffffffff8111156125f6576125f56120a8565b5b6126028882890161237e565b9150509295509295909350565b61261881612228565b82525050565b6000602082019050612633600083018461260f565b92915050565b6004811061264657600080fd5b50565b60008135905061265881612639565b92915050565b60008060408385031215612675576126746120a3565b5b6000612683858286016121b3565b925050602061269485828601612649565b9150509250929050565b600082825260208201905092915050565b7f5061796d656e74206665652068617320746f206265206269676765722074686160008201527f6e20300000000000000000000000000000000000000000000000000000000000602082015250565b600061270b60238361269e565b9150612716826126af565b604082019050919050565b6000602082019050818103600083015261273a816126fe565b9050919050565b7f5061796d656e74206665652064656e6f6d696e61746f722068617320746f206260008201527f6520626967676572207468616e20300000000000000000000000000000000000602082015250565b600061279d602f8361269e565b91506127a882612741565b604082019050919050565b600060208201905081810360008301526127cc81612790565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061280d82612168565b915061281883612168565b92508282039050818111156128305761282f6127d3565b5b92915050565b600081519050919050565b60005b8381101561285f578082015181840152602081019050612844565b60008484015250505050565b600061287682612836565b612880818561269e565b9350612890818560208601612841565b61289981612270565b840191505092915050565b600060408201905081810360008301526128be818561286b565b90506128cd6020830184612172565b9392505050565b600081905092915050565b50565b60006128ef6000836128d4565b91506128fa826128df565b600082019050919050565b6000612910826128e2565b9150819050919050565b7f4661696c656420746f2077697468647261772e00000000000000000000000000600082015250565b600061295060138361269e565b915061295b8261291a565b602082019050919050565b6000602082019050818103600083015261297f81612943565b9050919050565b7f4f7065726174696f6e206e6f7420737570706f72746564000000000000000000600082015250565b60006129bc60178361269e565b91506129c782612986565b602082019050919050565b600060208201905081810360008301526129eb816129af565b9050919050565b600081519050612a018161219c565b92915050565b600060208284031215612a1d57612a1c6120a3565b5b6000612a2b848285016129f2565b91505092915050565b6000604082019050612a49600083018561260f565b612a566020830184612172565b9392505050565b612a6681612132565b8114612a7157600080fd5b50565b600081519050612a8381612a5d565b92915050565b600060208284031215612a9f57612a9e6120a3565b5b6000612aad84828501612a74565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000612b4160268361269e565b9150612b4c82612ae5565b604082019050919050565b60006020820190508181036000830152612b7081612b34565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000612bad60208361269e565b9150612bb882612b77565b602082019050919050565b60006020820190508181036000830152612bdc81612ba0565b9050919050565b6000612bee82612168565b9150612bf983612168565b9250828202612c0781612168565b91508282048414831517612c1e57612c1d6127d3565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000612c5f82612168565b9150612c6a83612168565b925082612c7a57612c79612c25565b5b828204905092915050565b7f56616c75652073656e7420697320736d616c6c6572207468616e206d696e696d60008201527f616c206665652e00000000000000000000000000000000000000000000000000602082015250565b6000612ce160278361269e565b9150612cec82612c85565b604082019050919050565b60006020820190508181036000830152612d1081612cd4565b9050919050565b6000819050919050565b612d2a81612d17565b82525050565b612d3981612228565b82525050565b600067ffffffffffffffff82169050919050565b612d5c81612d3f565b82525050565b612d6b81612132565b82525050565b600081519050919050565b600082825260208201905092915050565b6000612d9882612d71565b612da28185612d7c565b9350612db2818560208601612841565b612dbb81612270565b840191505092915050565b612dcf81612168565b82525050565b600060c083016000830151612ded6000860182612d30565b506020830151612e006020860182612d53565b506040830151612e136040860182612d62565b506060830151612e266060860182612d21565b5060808301518482036080860152612e3e8282612d8d565b91505060a0830151612e5360a0860182612dc6565b508091505092915050565b6000604083016000830151612e766000860182612d21565b5060208301518482036020860152612e8e8282612dd5565b9150508091505092915050565b60006020820190508181036000830152612eb58184612e5e565b905092915050565b612ec681612d17565b8114612ed157600080fd5b50565b600081519050612ee381612ebd565b92915050565b600060208284031215612eff57612efe6120a3565b5b6000612f0d84828501612ed4565b91505092915050565b7f4661696c656420746f2073656e64000000000000000000000000000000000000600082015250565b6000612f4c600e8361269e565b9150612f5782612f16565b602082019050919050565b60006020820190508181036000830152612f7b81612f3f565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000612fb8601f8361269e565b9150612fc382612f82565b602082019050919050565b60006020820190508181036000830152612fe781612fab565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126130495761304861301d565b5b80840192508235915067ffffffffffffffff82111561306b5761306a613022565b5b60208301925060018202360383131561308757613086613027565b5b509250929050565b600061309a82612168565b91506130a583612168565b92508282019050808211156130bd576130bc6127d3565b5b92915050565b7f43616e27742073656e64206d6f7265207468616e206d73672e76616c75650000600082015250565b60006130f9601e8361269e565b9150613104826130c3565b602082019050919050565b60006020820190508181036000830152613128816130ec565b9050919050565b600061313a82612d71565b61314481856128d4565b9350613154818560208601612841565b80840191505092915050565b600061316c828461312f565b915081905092915050565b600061318282612168565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036131b4576131b36127d3565b5b600182019050919050565b60006060820190506131d4600083018661260f565b6131e1602083018561260f565b6131ee6040830184612172565b949350505050565b7f4661696c656420746f207472616e7366657220746f6b656e0000000000000000600082015250565b600061322c60188361269e565b9150613237826131f6565b602082019050919050565b6000602082019050818103600083015261325b8161321f565b9050919050565b600082825260208201905092915050565b6000613280600083613262565b915061328b826128df565b600082019050919050565b600060a0820190506132ab600083018761260f565b6132b8602083018661260f565b6132c56040830185612172565b6132d26060830184612172565b81810360808301526132e381613273565b905095945050505050565b6000608082019050613303600083018661260f565b613310602083018561260f565b61331d6040830184612172565b818103606083015261332e81613273565b9050949350505050565b600061334382612d71565b61334d8185613262565b935061335d818560208601612841565b61336681612270565b840191505092915050565b6000602082019050818103600083015261338b8184613338565b905092915050565b60006133a66133a1846122fc565b6122e1565b9050828152602081018484840111156133c2576133c161226b565b5b6133cd848285612841565b509392505050565b600082601f8301126133ea576133e9612266565b5b81516133fa848260208601613393565b91505092915050565b600060208284031215613419576134186120a3565b5b600082015167ffffffffffffffff811115613437576134366120a8565b5b613443848285016133d5565b91505092915050565b60006020820190508181036000830152613466818461286b565b905092915050565b600069ffffffffffffffffffff82169050919050565b61348d8161346e565b811461349857600080fd5b50565b6000815190506134aa81613484565b92915050565b6000819050919050565b6134c3816134b0565b81146134ce57600080fd5b50565b6000815190506134e0816134ba565b92915050565b600080600080600060a08688031215613502576135016120a3565b5b60006135108882890161349b565b9550506020613521888289016134d1565b9450506040613532888289016129f2565b9350506060613543888289016129f2565b92505060806135548882890161349b565b9150509295509295909350565b7f556e61626c6520746f207265747269657665204d415449432070726963652e00600082015250565b6000613597601f8361269e565b91506135a282613561565b602082019050919050565b600060208201905081810360008301526135c68161358a565b9050919050565b600060ff82169050919050565b6135e3816135cd565b81146135ee57600080fd5b50565b600081519050613600816135da565b92915050565b60006020828403121561361c5761361b6120a3565b5b600061362a848285016135f1565b91505092915050565b60008160011c9050919050565b6000808291508390505b600185111561368a57808604811115613666576136656127d3565b5b60018516156136755780820291505b808102905061368385613633565b945061364a565b94509492505050565b6000826136a3576001905061375f565b816136b1576000905061375f565b81600181146136c757600281146136d157613700565b600191505061375f565b60ff8411156136e3576136e26127d3565b5b8360020a9150848211156136fa576136f96127d3565b5b5061375f565b5060208310610133831016604e8410600b84101617156137355782820a9050838111156137305761372f6127d3565b5b61375f565b6137428484846001613640565b92509050818404811115613759576137586127d3565b5b81810290505b9392505050565b600061377182612168565b915061377c836135cd565b92506137a97fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484613693565b90509291505056fea264697066735822122013d83d2ed742d0e6368e6d5c8b4378652da5bb3ef11c058842b6e287f5eae11164736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000013e3ee699d1909e989722e753853ae30b17e08c50000000000000000000000004200000000000000000000000000000000000021
-----Decoded View---------------
Arg [0] : _nativeUsdAggregator (address): 0x13e3Ee699D1909E989722E753853AE30b17e08c5
Arg [1] : _eas (address): 0x4200000000000000000000000000000000000021
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000013e3ee699d1909e989722e753853ae30b17e08c5
Arg [1] : 0000000000000000000000004200000000000000000000000000000000000021
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$17.24
Net Worth in ETH
0.005838
Token Allocations
ETH
95.64%
USDC
2.97%
DAI
0.76%
Others
0.64%
Multichain Portfolio | 35 Chains
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.