Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- SideTokenFactory
- Optimization enabled
- true
- Compiler version
- v0.8.9+commit.e5eed63a
- Optimization runs
- 200
- EVM Version
- istanbul
- Verified at
- 2024-10-18T19:25:55.248582Z
contracts/SideTokenFactory/SideTokenFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
import "../zeppelin/ownership/Secondary.sol";
import "../interface/ISideTokenFactory.sol";
import "../SideToken/SideToken.sol";
contract SideTokenFactory is ISideTokenFactory, Secondary {
function createSideToken(string calldata name, string calldata symbol, uint256 granularity)
external onlyPrimary override returns(address) {
address sideToken = address(new SideToken(name, symbol, primary(), granularity));
emit SideTokenCreated(sideToken, symbol, granularity);
return sideToken;
}
}
contracts/zeppelin/token/ERC777/IERC777Sender.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
/**
* @dev Interface of the ERC777TokensSender standard as defined in the EIP.
*
* `IERC777` Token holders can be notified of operations performed on their
* tokens by having a contract implement this interface (contract holders can be
* their own implementer) and registering it on the
* [ERC1820 global registry](https://eips.ethereum.org/EIPS/eip-1820).
*
* See `IERC1820Registry` and `ERC1820Implementer`.
*/
interface IERC777Sender {
/**
* @dev Called by an `IERC777` token contract whenever a registered holder's
* (`from`) tokens are about to be moved or destroyed. The type of operation
* is conveyed by `to` being the zero address or not.
*
* This call occurs _before_ the token contract's state is updated, so
* `IERC777.balanceOf`, etc., can be used to query the pre-operation state.
*
* This function may revert to prevent the operation from being executed.
*/
function tokensToSend(
address operator,
address from,
address to,
uint amount,
bytes calldata userData,
bytes calldata operatorData
) external;
}
contracts/zeppelin/utils/Address.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
contracts/SideToken/SideToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
import "../zeppelin/token/ERC777/ERC777.sol";
import "../interface/IERC677Receiver.sol";
import "../interface/ISideToken.sol";
import "../lib/LibEIP712.sol";
contract SideToken is ISideToken, ERC777 {
using SafeMath for uint256;
address public minter;
uint256 private _granularity;
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2612.md
bytes32 public domainSeparator;
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
mapping(address => uint) public nonces;
// ERC677 Transfer Event
event Transfer(address,address,uint256,bytes);
constructor(string memory _tokenName, string memory _tokenSymbol, address _minterAddr, uint256 _newGranularity)
ERC777(_tokenName, _tokenSymbol, new address[](0)) {
require(_minterAddr != address(0), "SideToken: Empty Minter");
require(_newGranularity >= 1, "SideToken: Granularity < 1");
minter = _minterAddr;
_granularity = _newGranularity;
domainSeparator = LibEIP712.hashEIP712Domain(
name(),
"1",
block.chainid,
address(this)
);
}
modifier onlyMinter() {
require(_msgSender() == minter, "SideToken: Caller is not the minter");
_;
}
function mint(
address account,
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
)
external onlyMinter override
{
_mint(_msgSender(), account, amount, userData, operatorData);
}
/**
* @dev ERC677 transfer token with additional data if the recipient is a contact.
* @param recipient The address to transfer to.
* @param amount The amount to be transferred.
* @param data The extra data to be passed to the receiving contract.
*/
function transferAndCall(address recipient, uint amount, bytes calldata data)
external returns (bool success)
{
address from = _msgSender();
_send(from, from, recipient, amount, data, "", false);
emit Transfer(from, recipient, amount, data);
IERC677Receiver(recipient).onTokenTransfer(from, amount, data);
return true;
}
function granularity() public view override returns (uint256) {
return _granularity;
}
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2612.md
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
require(deadline >= block.timestamp, "SideToken: EXPIRED"); // solhint-disable-line not-rely-on-time
bytes32 digest = LibEIP712.hashEIP712Message(
domainSeparator,
keccak256(
abi.encode(
PERMIT_TYPEHASH,
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
);
address recoveredAddress = ecrecover(digest, v, r, s);
require(recoveredAddress != address(0) && recoveredAddress == owner, "SideToken: INVALID_SIGNATURE");
_approve(owner, spender, value);
}
}
contracts/interface/IERC677Receiver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
interface IERC677Receiver {
function onTokenTransfer(address _sender, uint _value, bytes calldata _data) external;
}
contracts/interface/ISideToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
interface ISideToken {
function mint(address account, uint256 amount, bytes calldata userData, bytes calldata operatorData) external;
}
contracts/interface/ISideTokenFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
interface ISideTokenFactory {
function createSideToken(string calldata name, string calldata symbol, uint256 granularity) external returns(address);
event SideTokenCreated(address indexed sideToken, string symbol, uint256 granularity);
}
contracts/lib/LibEIP712.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
// https://github.com/0xProject/0x-monorepo/blob/development/contracts/utils/contracts/src/LibEIP712.sol
library LibEIP712 {
// Hash of the EIP712 Domain Separator Schema
// keccak256(abi.encodePacked(
// "EIP712Domain(",
// "string name,",
// "string version,",
// "uint256 chainId,",
// "address verifyingContract",
// ")"
// ))
bytes32 constant internal _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;
/// @dev Calculates a EIP712 domain separator.
/// @param name The EIP712 domain name.
/// @param version The EIP712 domain version.
/// @param verifyingContract The EIP712 verifying contract.
/// @return result EIP712 domain separator.
function hashEIP712Domain(
string memory name,
string memory version,
uint256 chainId,
address verifyingContract
)
internal
pure
returns (bytes32 result)
{
bytes32 schemaHash = _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH;
// Assembly for more efficient computing:
// keccak256(abi.encodePacked(
// _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH,
// keccak256(bytes(name)),
// keccak256(bytes(version)),
// chainId,
// uint256(verifyingContract)
// ))
// solium-disable-next-line security/no-inline-assembly
assembly {
// Calculate hashes of dynamic data
let nameHash := keccak256(add(name, 32), mload(name))
let versionHash := keccak256(add(version, 32), mload(version))
// Load free memory pointer
let memPtr := mload(64)
// Store params in memory
mstore(memPtr, schemaHash)
mstore(add(memPtr, 32), nameHash)
mstore(add(memPtr, 64), versionHash)
mstore(add(memPtr, 96), chainId)
mstore(add(memPtr, 128), verifyingContract)
// Compute hash
result := keccak256(memPtr, 160)
}
return result;
}
/// @dev Calculates EIP712 encoding for a hash struct with a given domain hash.
/// @param eip712DomainHash Hash of the domain domain separator data, computed
/// with getDomainHash().
/// @param hashStruct The EIP712 hash struct.
/// @return result EIP712 hash applied to the given EIP712 Domain.
function hashEIP712Message(bytes32 eip712DomainHash, bytes32 hashStruct)
internal
pure
returns (bytes32 result)
{
// Assembly for more efficient computing:
// keccak256(abi.encodePacked(
// EIP191_HEADER,
// EIP712_DOMAIN_HASH,
// hashStruct
// ));
// solium-disable-next-line security/no-inline-assembly
assembly {
// Load free memory pointer
let memPtr := mload(64)
mstore(memPtr, 0x1901000000000000000000000000000000000000000000000000000000000000) // EIP191 header
mstore(add(memPtr, 2), eip712DomainHash) // EIP712 domain hash
mstore(add(memPtr, 34), hashStruct) // Hash of struct
// Compute hash
result := keccak256(memPtr, 66)
}
return result;
}
}
contracts/zeppelin/GSN/Context.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
/*
* @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 GSN 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 returns (address payable) {
return payable(msg.sender);
}
function _msgData() internal view returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
contracts/zeppelin/introspection/IERC1820Registry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
/**
* @dev Interface of the global ERC1820 Registry, as defined in the
* https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register
* implementers for interfaces in this registry, as well as query support.
*
* Implementers may be shared by multiple accounts, and can also implement more
* than a single interface for each account. Contracts can implement interfaces
* for themselves, but externally-owned accounts (EOA) must delegate this to a
* contract.
*
* {IERC165} interfaces can also be queried via the registry.
*
* For an in-depth explanation and source code analysis, see the EIP text.
*/
interface IERC1820Registry {
/**
* @dev Sets `newManager` as the manager for `account`. A manager of an
* account is able to set interface implementers for it.
*
* By default, each account is its own manager. Passing a value of `0x0` in
* `newManager` will reset the manager to this initial state.
*
* Emits a {ManagerChanged} event.
*
* Requirements:
*
* - the caller must be the current manager for `account`.
*/
function setManager(address account, address newManager) external;
/**
* @dev Returns the manager for `account`.
*
* See {setManager}.
*/
function getManager(address account) external view returns (address);
/**
* @dev Sets the `implementer` contract as `account`'s implementer for
* `interfaceHash`.
*
* `account` being the zero address is an alias for the caller's address.
* The zero address can also be used in `implementer` to remove an old one.
*
* See {interfaceHash} to learn how these are created.
*
* Emits an {InterfaceImplementerSet} event.
*
* Requirements:
*
* - the caller must be the current manager for `_account`.
* - `_interfaceHash` must not be an {IERC165} interface id (i.e. it must not
* end in 28 zeroes).
* - `_implementer` must implement {IERC1820Implementer} and return true when
* queried for support, unless `implementer` is the caller. See
* {IERC1820Implementer-canImplementInterfaceForAddress}.
*/
function setInterfaceImplementer(address _account, bytes32 _interfaceHash, address _implementer) external;
/**
* @dev Returns the implementer of `_interfaceHash` for `_account`. If no such
* implementer is registered, returns the zero address.
*
* If `_interfaceHash` is an {IERC165} interface id (i.e. it ends with 28
* zeroes), `_account` will be queried for support of it.
*
* `account` being the zero address is an alias for the caller's address.
*/
function getInterfaceImplementer(address _account, bytes32 _interfaceHash) external view returns (address);
/**
* @dev Returns the interface hash for an `interfaceName`, as defined in the
* corresponding
* https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP].
*/
function interfaceHash(string calldata interfaceName) external pure returns (bytes32);
/**
* @notice Updates the cache with whether the contract implements an ERC165 interface or not.
* @param account Address of the contract for which to update the cache.
* @param interfaceId ERC165 interface for which to update the cache.
*/
function updateERC165Cache(address account, bytes4 interfaceId) external;
/**
* @notice Checks whether a contract implements an ERC165 interface or not.
* If the result is not cached a direct lookup on the contract address is performed.
* If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
* {updateERC165Cache} with the contract address.
* @param account Address of the contract to check.
* @param interfaceId ERC165 interface to check.
* @return True if `account` implements `interfaceId`, false otherwise.
*/
function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);
/**
* @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
* @param account Address of the contract to check.
* @param interfaceId ERC165 interface to check.
* @return True if `account` implements `interfaceId`, false otherwise.
*/
function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);
event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);
event ManagerChanged(address indexed account, address indexed newManager);
}
contracts/zeppelin/math/SafeMath.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*
* _Available since v2.4.0._
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
contracts/zeppelin/ownership/Secondary.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
import "../GSN/Context.sol";
/**
* @dev A Secondary contract can only be used by its primary account (the one that created it).
*/
abstract contract Secondary is Context {
address private _primary;
/**
* @dev Emitted when the primary contract changes.
*/
event PrimaryTransferred(
address recipient
);
/**
* @dev Sets the primary account to the one that is creating the Secondary contract.
*/
constructor () {
_primary = _msgSender();
emit PrimaryTransferred(_primary);
}
/**
* @dev Reverts if called from any account other than the primary.
*/
modifier onlyPrimary() {
require(_msgSender() == _primary, "Secondary: caller is not the primary account");
_;
}
/**
* @return the address of the primary.
*/
function primary() public view returns (address) {
return _primary;
}
/**
* @dev Transfers contract to a new primary.
* @param recipient The address of new primary.
*/
function transferPrimary(address recipient) public onlyPrimary {
require(recipient != address(0), "Secondary: new primary is the zero address");
_primary = recipient;
emit PrimaryTransferred(_primary);
}
}
contracts/zeppelin/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see {ERC20Detailed}.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contracts/zeppelin/token/ERC777/ERC777.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
import "../../GSN/Context.sol";
import "./IERC777.sol";
import "./IERC777Recipient.sol";
import "./IERC777Sender.sol";
import "../../token/ERC20/IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
import "../../introspection/IERC1820Registry.sol";
/**
* @dev Implementation of the {IERC777} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
*
* Support for ERC20 is included in this contract, as specified by the EIP: both
* the ERC777 and ERC20 interfaces can be safely used when interacting with it.
* Both {IERC777-Sent} and {IERC20-Transfer} events are emitted on token
* movements.
*
* Additionally, the {IERC777-granularity} value is hard-coded to `1`, meaning that there
* are no special restrictions in the amount of tokens that created, moved, or
* destroyed. This makes integration with ERC20 applications seamless.
*/
contract ERC777 is Context, IERC777, IERC20 {
using SafeMath for uint256;
using Address for address;
IERC1820Registry constant private _erc1820 = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
mapping(address => uint256) private _balances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
// We inline the result of the following hashes because Solidity doesn't resolve them at compile time.
// See https://github.com/ethereum/solidity/issues/4024.
// keccak256("ERC777TokensSender")
bytes32 constant private TOKENS_SENDER_INTERFACE_HASH =
0x29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe895;
// keccak256("ERC777TokensRecipient")
bytes32 constant private TOKENS_RECIPIENT_INTERFACE_HASH =
0xb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b;
// This isn't ever read from - it's only used to respond to the defaultOperators query.
address[] private _defaultOperatorsArray;
// Immutable, but accounts may revoke them (tracked in __revokedDefaultOperators).
mapping(address => bool) private _defaultOperators;
// For each account, a mapping of its operators and revoked default operators.
mapping(address => mapping(address => bool)) private _operators;
mapping(address => mapping(address => bool)) private _revokedDefaultOperators;
// ERC20-allowances
mapping (address => mapping (address => uint256)) private _allowances;
/**
* @dev `defaultOperators` may be an empty array.
*/
constructor(
string memory aName,
string memory aSymbol,
address[] memory theDefaultOperators
) {
_name = aName;
_symbol = aSymbol;
_defaultOperatorsArray = theDefaultOperators;
for (uint256 i = 0; i < _defaultOperatorsArray.length; i++) {
_defaultOperators[_defaultOperatorsArray[i]] = true;
}
// register interfaces
_erc1820.setInterfaceImplementer(address(this), keccak256("ERC777Token"), address(this));
_erc1820.setInterfaceImplementer(address(this), keccak256("ERC20Token"), address(this));
}
/**
* @dev See {IERC777-name}.
*/
function name() public view override(IERC777) returns (string memory) {
return _name;
}
/**
* @dev See {IERC777-symbol}.
*/
function symbol() public view override(IERC777) returns (string memory) {
return _symbol;
}
/**
* @dev See {ERC20Detailed-decimals}.
*
* Always returns 18, as per the
* [ERC777 EIP](https://eips.ethereum.org/EIPS/eip-777#backward-compatibility).
*/
function decimals() public pure override returns (uint8) {
return 18;
}
/**
* @dev See {IERC777-granularity}.
*
* This implementation always returns `1`.
*/
function granularity() public view virtual override(IERC777) returns (uint256) {
return 1;
}
/**
* @dev See {IERC777-totalSupply}.
*/
function totalSupply() public view override(IERC20, IERC777) returns (uint256) {
return _totalSupply;
}
/**
* @dev Returns the amount of tokens owned by an account (`tokenHolder`).
*/
function balanceOf(address tokenHolder) public view override(IERC20, IERC777) returns (uint256) {
return _balances[tokenHolder];
}
/**
* @dev See {IERC777-send}.
*
* Also emits a {Transfer} event for ERC20 compatibility.
*/
function send(address recipient, uint256 amount, bytes calldata data) external override(IERC777) {
_send(_msgSender(), _msgSender(), recipient, amount, data, "", true);
}
/**
* @dev See {IERC20-transfer}.
*
* Unlike `send`, `recipient` is _not_ required to implement the {IERC777Recipient}
* interface if it is a contract.
*
* Also emits a {Sent} event.
*/
function transfer(address recipient, uint256 amount) external override(IERC20) returns (bool) {
require(recipient != address(0), "ERC777: transfer to zero address");
address from = _msgSender();
_callTokensToSend(from, from, recipient, amount, "", "");
_move(from, from, recipient, amount, "", "");
_callTokensReceived(from, from, recipient, amount, "", "", false);
return true;
}
/**
* @dev See {IERC777-burn}.
*
* Also emits a {Transfer} event for ERC20 compatibility.
*/
function burn(uint256 amount, bytes calldata data) external override(IERC777) {
_burn(_msgSender(), _msgSender(), amount, data, "");
}
/**
* @dev See {IERC777-isOperatorFor}.
*/
function isOperatorFor(
address operator,
address tokenHolder
) public view override(IERC777) returns (bool) {
return operator == tokenHolder ||
(_defaultOperators[operator] && !_revokedDefaultOperators[tokenHolder][operator]) ||
_operators[tokenHolder][operator];
}
/**
* @dev See {IERC777-authorizeOperator}.
*/
function authorizeOperator(address operator) external override(IERC777) {
require(_msgSender() != operator, "ERC777: authorizing self as operator");
if (_defaultOperators[operator]) {
delete _revokedDefaultOperators[_msgSender()][operator];
} else {
_operators[_msgSender()][operator] = true;
}
emit AuthorizedOperator(operator, _msgSender());
}
/**
* @dev See {IERC777-revokeOperator}.
*/
function revokeOperator(address operator) external override(IERC777) {
require(operator != _msgSender(), "ERC777: revoking self as operator");
if (_defaultOperators[operator]) {
_revokedDefaultOperators[_msgSender()][operator] = true;
} else {
delete _operators[_msgSender()][operator];
}
emit RevokedOperator(operator, _msgSender());
}
/**
* @dev See {IERC777-defaultOperators}.
*/
function defaultOperators() public view override(IERC777) returns (address[] memory) {
return _defaultOperatorsArray;
}
/**
* @dev See {IERC777-operatorSend}.
*
* Emits {Sent} and {Transfer} events.
*/
function operatorSend(
address sender,
address recipient,
uint256 amount,
bytes calldata data,
bytes calldata operatorData
)
external override(IERC777)
{
require(isOperatorFor(_msgSender(), sender), "ERC777: caller is not an operator");
_send(_msgSender(), sender, recipient, amount, data, operatorData, true);
}
/**
* @dev See {IERC777-operatorBurn}.
*
* Emits {Burned} and {Transfer} events.
*/
function operatorBurn(address account, uint256 amount, bytes calldata data, bytes calldata operatorData)
external override(IERC777) {
require(isOperatorFor(_msgSender(), account), "ERC777: caller is not an operator");
_burn(_msgSender(), account, amount, data, operatorData);
}
/**
* @dev See {IERC20-allowance}.
*
* Note that operator and allowance concepts are orthogonal: operators may
* not have allowance, and accounts with allowance may not be operators
* themselves.
*/
function allowance(address holder, address spender)
public view override(IERC20) returns (uint256) {
return _allowances[holder][spender];
}
/**
* @dev See {IERC20-approve}.
*
* Note that accounts cannot have allowance issued by their operators.
*/
function approve(address spender, uint256 value) external override(IERC20) returns (bool) {
address holder = _msgSender();
_approve(holder, spender, value);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Note that operator and allowance concepts are orthogonal: operators cannot
* call `transferFrom` (unless they have allowance), and accounts with
* allowance cannot call `operatorSend` (unless they are operators).
*
* Emits {Sent}, {Transfer} and {Approval} events.
*/
function transferFrom(address holder, address recipient, uint256 amount)
external override(IERC20) returns (bool) {
require(recipient != address(0), "ERC777: transfer to zero address");
require(holder != address(0), "ERC777: transfer from zero address");
address spender = _msgSender();
_callTokensToSend(spender, holder, recipient, amount, "", "");
_move(spender, holder, recipient, amount, "", "");
_approve(holder, spender, _allowances[holder][spender].sub(amount, "ERC777: transfer amount exceeds allowance"));
_callTokensReceived(spender, holder, recipient, amount, "", "", false);
return true;
}
/**
* @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* If a send hook is registered for `account`, the corresponding function
* will be called with `operator`, `data` and `operatorData`.
*
* See {IERC777Sender} and {IERC777Recipient}.
*
* Emits {Minted} and {Transfer} events.
*
* Requirements
*
* - `account` cannot be the zero address.
* - if `account` is a contract, it must implement the {IERC777Recipient}
* interface.
*/
function _mint(
address operator,
address account,
uint256 amount,
bytes memory userData,
bytes memory operatorData
)
internal
{
require(account != address(0), "ERC777: mint to zero address");
// Update state variables
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
_callTokensReceived(operator, address(0), account, amount, userData, operatorData, true);
emit Minted(operator, account, amount, userData, operatorData);
emit Transfer(address(0), account, amount);
}
/**
* @dev Send tokens
* @param operator address operator requesting the transfer
* @param from address token holder address
* @param to address recipient address
* @param amount uint256 amount of tokens to transfer
* @param userData bytes extra information provided by the token holder (if any)
* @param operatorData bytes extra information provided by the operator (if any)
* @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
*/
function _send(
address operator,
address from,
address to,
uint256 amount,
bytes memory userData,
bytes memory operatorData,
bool requireReceptionAck
)
internal
{
require(from != address(0), "ERC777: send from zero address");
require(to != address(0), "ERC777: send to zero address");
_callTokensToSend(operator, from, to, amount, userData, operatorData);
_move(operator, from, to, amount, userData, operatorData);
_callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck);
}
/**
* @dev Burn tokens
* @param operator address operator requesting the operation
* @param from address token holder address
* @param amount uint256 amount of tokens to burn
* @param data bytes extra information provided by the token holder
* @param operatorData bytes extra information provided by the operator (if any)
*/
function _burn(
address operator,
address from,
uint256 amount,
bytes memory data,
bytes memory operatorData
)
internal
{
require(from != address(0), "ERC777: burn from zero address");
_callTokensToSend(operator, from, address(0), amount, data, operatorData);
// Update state variables
_balances[from] = _balances[from].sub(amount, "ERC777: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Burned(operator, from, amount, data, operatorData);
emit Transfer(from, address(0), amount);
}
function _move(
address operator,
address from,
address to,
uint256 amount,
bytes memory userData,
bytes memory operatorData
)
internal
{
_balances[from] = _balances[from].sub(amount, "ERC777: transfer amount exceeds balance");
_balances[to] = _balances[to].add(amount);
emit Sent(operator, from, to, amount, userData, operatorData);
emit Transfer(from, to, amount);
}
function _approve(address holder, address spender, uint256 value) internal {
// TODO: restore this require statement if this function becomes internal, or is called at a new callsite. It is
// currently unnecessary.
//require(holder != address(0), "ERC777: approve from the zero address");
require(spender != address(0), "ERC777: approve to zero address");
_allowances[holder][spender] = value;
emit Approval(holder, spender, value);
}
/**
* @dev Call from.tokensToSend() if the interface is registered
* @param operator address operator requesting the transfer
* @param from address token holder address
* @param to address recipient address
* @param amount uint256 amount of tokens to transfer
* @param userData bytes extra information provided by the token holder (if any)
* @param operatorData bytes extra information provided by the operator (if any)
*/
function _callTokensToSend(
address operator,
address from,
address to,
uint256 amount,
bytes memory userData,
bytes memory operatorData
)
internal
{
address implementer = _erc1820.getInterfaceImplementer(from, TOKENS_SENDER_INTERFACE_HASH);
if (implementer != address(0)) {
IERC777Sender(implementer).tokensToSend(operator, from, to, amount, userData, operatorData);
}
}
/**
* @dev Call to.tokensReceived() if the interface is registered. Reverts if the recipient is a contract but
* tokensReceived() was not registered for the recipient
* @param operator address operator requesting the transfer
* @param from address token holder address
* @param to address recipient address
* @param amount uint256 amount of tokens to transfer
* @param userData bytes extra information provided by the token holder (if any)
* @param operatorData bytes extra information provided by the operator (if any)
* @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
*/
function _callTokensReceived(
address operator,
address from,
address to,
uint256 amount,
bytes memory userData,
bytes memory operatorData,
bool requireReceptionAck
)
private
{
address implementer = _erc1820.getInterfaceImplementer(to, TOKENS_RECIPIENT_INTERFACE_HASH);
if (implementer != address(0)) {
IERC777Recipient(implementer).tokensReceived(operator, from, to, amount, userData, operatorData);
} else if (requireReceptionAck) {
require(!to.isContract(), "ERC777: token recipient contract has no implementer for ERC777TokensRecipient");
}
}
}
contracts/zeppelin/token/ERC777/IERC777.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
/**
* @dev Interface of the ERC777Token standard as defined in the EIP.
*
* This contract uses the
* [ERC1820 registry standard](https://eips.ethereum.org/EIPS/eip-1820) to let
* token holders and recipients react to token movements by using setting implementers
* for the associated interfaces in said registry. See `IERC1820Registry` and
* `ERC1820Implementer`.
*/
interface IERC777 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the smallest part of the token that is not divisible. This
* means all token operations (creation, movement and destruction) must have
* amounts that are a multiple of this number.
*
* For most token contracts, this value will equal 1.
*/
function granularity() external view returns (uint256);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by an account (`owner`).
*/
function balanceOf(address owner) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* If send or receive hooks are registered for the caller and `recipient`,
* the corresponding functions will be called with `data` and empty
* `operatorData`. See `IERC777Sender` and `IERC777Recipient`.
*
* Emits a `Sent` event.
*
* Requirements
*
* - the caller must have at least `amount` tokens.
* - `recipient` cannot be the zero address.
* - if `recipient` is a contract, it must implement the `tokensReceived`
* interface.
*/
function send(address recipient, uint256 amount, bytes calldata data) external;
/**
* @dev Destroys `amount` tokens from the caller's account, reducing the
* total supply.
*
* If a send hook is registered for the caller, the corresponding function
* will be called with `data` and empty `operatorData`. See `IERC777Sender`.
*
* Emits a `Burned` event.
*
* Requirements
*
* - the caller must have at least `amount` tokens.
*/
function burn(uint256 amount, bytes calldata data) external;
/**
* @dev Returns true if an account is an operator of `tokenHolder`.
* Operators can send and burn tokens on behalf of their owners. All
* accounts are their own operator.
*
* See `operatorSend` and `operatorBurn`.
*/
function isOperatorFor(address operator, address tokenHolder) external view returns (bool);
/**
* @dev Make an account an operator of the caller.
*
* See `isOperatorFor`.
*
* Emits an `AuthorizedOperator` event.
*
* Requirements
*
* - `operator` cannot be calling address.
*/
function authorizeOperator(address operator) external;
/**
* @dev Make an account an operator of the caller.
*
* See `isOperatorFor` and `defaultOperators`.
*
* Emits a `RevokedOperator` event.
*
* Requirements
*
* - `operator` cannot be calling address.
*/
function revokeOperator(address operator) external;
/**
* @dev Returns the list of default operators. These accounts are operators
* for all token holders, even if `authorizeOperator` was never called on
* them.
*
* This list is immutable, but individual holders may revoke these via
* `revokeOperator`, in which case `isOperatorFor` will return false.
*/
function defaultOperators() external view returns (address[] memory);
/**
* @dev Moves `amount` tokens from `sender` to `recipient`. The caller must
* be an operator of `sender`.
*
* If send or receive hooks are registered for `sender` and `recipient`,
* the corresponding functions will be called with `data` and
* `operatorData`. See `IERC777Sender` and `IERC777Recipient`.
*
* Emits a `Sent` event.
*
* Requirements
*
* - `sender` cannot be the zero address.
* - `sender` must have at least `amount` tokens.
* - the caller must be an operator for `sender`.
* - `recipient` cannot be the zero address.
* - if `recipient` is a contract, it must implement the `tokensReceived`
* interface.
*/
function operatorSend(
address sender,
address recipient,
uint256 amount,
bytes calldata data,
bytes calldata operatorData
) external;
/**
* @dev Destoys `amount` tokens from `account`, reducing the total supply.
* The caller must be an operator of `account`.
*
* If a send hook is registered for `account`, the corresponding function
* will be called with `data` and `operatorData`. See `IERC777Sender`.
*
* Emits a `Burned` event.
*
* Requirements
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
* - the caller must be an operator for `account`.
*/
function operatorBurn(
address account,
uint256 amount,
bytes calldata data,
bytes calldata operatorData
) external;
event Sent(
address indexed operator,
address indexed from,
address indexed to,
uint256 amount,
bytes data,
bytes operatorData
);
function decimals() external returns (uint8);
event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);
event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);
event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
event RevokedOperator(address indexed operator, address indexed tokenHolder);
}
contracts/zeppelin/token/ERC777/IERC777Recipient.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
/**
* @dev Interface of the ERC777TokensRecipient standard as defined in the EIP.
*
* Accounts can be notified of `IERC777` tokens being sent to them by having a
* contract implement this interface (contract holders can be their own
* implementer) and registering it on the
* [ERC1820 global registry](https://eips.ethereum.org/EIPS/eip-1820).
*
* See `IERC1820Registry` and `ERC1820Implementer`.
*/
interface IERC777Recipient {
/**
* @dev Called by an `IERC777` token contract whenever tokens are being
* moved or created into a registered account (`to`). The type of operation
* is conveyed by `from` being the zero address or not.
*
* This call occurs _after_ the token contract's state is updated, so
* `IERC777.balanceOf`, etc., can be used to query the post-operation state.
*
* This function may revert to prevent the operation from being executed.
*/
function tokensReceived(
address operator,
address from,
address to,
uint amount,
bytes calldata userData,
bytes calldata operatorData
) external;
}
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata","devdoc","userdoc","storageLayout","evm.gasEstimates"],"":["ast"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":true},"libraries":{},"evmVersion":"istanbul"}
Contract ABI
[{"type":"event","name":"PrimaryTransferred","inputs":[{"type":"address","name":"recipient","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"SideTokenCreated","inputs":[{"type":"address","name":"sideToken","internalType":"address","indexed":true},{"type":"string","name":"symbol","internalType":"string","indexed":false},{"type":"uint256","name":"granularity","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"createSideToken","inputs":[{"type":"string","name":"name","internalType":"string"},{"type":"string","name":"symbol","internalType":"string"},{"type":"uint256","name":"granularity","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"primary","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferPrimary","inputs":[{"type":"address","name":"recipient","internalType":"address"}]}]
Contract Creation Code
0x608060405234801561001057600080fd5b50600080546001600160a01b0319163390811790915560408051918252517f4101e71e974f68df5e9730cc223280b41654676bbb052cdcc735c3337e64d2d99181900360200190a1612c5a806100676000396000f3fe60806040523480156200001157600080fd5b5060043610620000465760003560e01c80632348238c146200004b57806326d9e9631462000064578063c6dbdf611462000097575b600080fd5b620000626200005c36600462000296565b620000a9565b005b6200007b6200007536600462000314565b620001a7565b6040516001600160a01b03909116815260200160405180910390f35b6000546001600160a01b03166200007b565b6000546001600160a01b0316336001600160a01b031614620000e85760405162461bcd60e51b8152600401620000df906200038f565b60405180910390fd5b6001600160a01b038116620001535760405162461bcd60e51b815260206004820152602a60248201527f5365636f6e646172793a206e6577207072696d61727920697320746865207a65604482015269726f206164647265737360b01b6064820152608401620000df565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f4101e71e974f68df5e9730cc223280b41654676bbb052cdcc735c3337e64d2d99060200160405180910390a150565b600080546001600160a01b0316336001600160a01b031614620001de5760405162461bcd60e51b8152600401620000df906200038f565b600086868686620001f76000546001600160a01b031690565b87604051620002069062000288565b620002179695949392919062000404565b604051809103906000f08015801562000234573d6000803e3d6000fd5b509050806001600160a01b03167ff57d2ded8330a4affd2fa52378069be534fe22288536537d1a1cfc061518450786868660405162000276939291906200044e565b60405180910390a29695505050505050565b6127b0806200047583390190565b600060208284031215620002a957600080fd5b81356001600160a01b0381168114620002c157600080fd5b9392505050565b60008083601f840112620002db57600080fd5b50813567ffffffffffffffff811115620002f457600080fd5b6020830191508360208285010111156200030d57600080fd5b9250929050565b6000806000806000606086880312156200032d57600080fd5b853567ffffffffffffffff808211156200034657600080fd5b6200035489838a01620002c8565b909750955060208801359150808211156200036e57600080fd5b506200037d88828901620002c8565b96999598509660400135949350505050565b6020808252602c908201527f5365636f6e646172793a2063616c6c6572206973206e6f74207468652070726960408201526b1b585c9e481858d8dbdd5b9d60a21b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6080815260006200041a60808301888a620003db565b82810360208401526200042f818789620003db565b6001600160a01b03959095166040840152505060600152949350505050565b60408152600062000464604083018587620003db565b905082602083015294935050505056fe60806040523480156200001157600080fd5b50604051620027b0380380620027b08339810160408190526200003491620005ff565b60408051600081526020808201909252855186928692916200005d916002919086019062000434565b5081516200007390600390602085019062000434565b50805162000089906004906020840190620004c3565b5060005b600454811015620000fd5760016005600060048481548110620000b457620000b462000692565b6000918252602080832091909101546001600160a01b031683528201929092526040019020805460ff191691151591909117905580620000f481620006a8565b9150506200008d565b506040516329965a1d60e01b815230600482018190527fac7fbab5f54a3ca8194167523c6753bfeb96a445279294b6125b68cce217705460248301526044820152731820a4b7618bde71dce8cdc73aab6c95905fad24906329965a1d90606401600060405180830381600087803b1580156200017857600080fd5b505af11580156200018d573d6000803e3d6000fd5b50506040516329965a1d60e01b815230600482018190527faea199e31a596269b42cdafd93407f14436db6e4cad65417994c2eb37381e05a60248301526044820152731820a4b7618bde71dce8cdc73aab6c95905fad2492506329965a1d9150606401600060405180830381600087803b1580156200020b57600080fd5b505af115801562000220573d6000803e3d6000fd5b50505050506001600160a01b038416151591506200028790505760405162461bcd60e51b815260206004820152601760248201527f53696465546f6b656e3a20456d707479204d696e74657200000000000000000060448201526064015b60405180910390fd5b6001811015620002da5760405162461bcd60e51b815260206004820152601a60248201527f53696465546f6b656e3a204772616e756c6172697479203c203100000000000060448201526064016200027e565b600980546001600160a01b0319166001600160a01b038416179055600a819055620003356200030862000343565b604051806040016040528060018152602001603160f81b8152504630620003dd60201b620010201760201c565b600b55506200070f92505050565b6060600280546200035490620006d2565b80601f01602080910402602001604051908101604052809291908181526020018280546200038290620006d2565b8015620003d35780601f10620003a757610100808354040283529160200191620003d3565b820191906000526020600020905b815481529060010190602001808311620003b557829003601f168201915b5050505050905090565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b8280546200044290620006d2565b90600052602060002090601f016020900481019282620004665760008555620004b1565b82601f106200048157805160ff1916838001178555620004b1565b82800160010185558215620004b1579182015b82811115620004b157825182559160200191906001019062000494565b50620004bf9291506200051b565b5090565b828054828255906000526020600020908101928215620004b1579160200282015b82811115620004b157825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620004e4565b5b80821115620004bf57600081556001016200051c565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200055a57600080fd5b81516001600160401b038082111562000577576200057762000532565b604051601f8301601f19908116603f01168101908282118183101715620005a257620005a262000532565b81604052838152602092508683858801011115620005bf57600080fd5b600091505b83821015620005e35785820183015181830184015290820190620005c4565b83821115620005f55760008385830101525b9695505050505050565b600080600080608085870312156200061657600080fd5b84516001600160401b03808211156200062e57600080fd5b6200063c8883890162000548565b955060208701519150808211156200065357600080fd5b50620006628782880162000548565b604087015190945090506001600160a01b03811681146200068257600080fd5b6060959095015193969295505050565b634e487b7160e01b600052603260045260246000fd5b6000600019821415620006cb57634e487b7160e01b600052601160045260246000fd5b5060010190565b600181811c90821680620006e757607f821691505b602082108114156200070957634e487b7160e01b600052602260045260246000fd5b50919050565b612091806200071f6000396000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c80637ecebe00116100de578063d95b637111610097578063f698da2511610071578063f698da2514610380578063fad8b32a14610389578063fc673c4f1461039c578063fe9d9303146103af57600080fd5b8063d95b637114610321578063dcdc7dd014610334578063dd62ed3e1461034757600080fd5b80637ecebe00146102ad578063959b8c3f146102cd57806395d89b41146102e05780639bd9bbc6146102e8578063a9059cbb146102fb578063d505accf1461030e57600080fd5b806330adf81f1161013057806330adf81f1461021e578063313ce567146102455780634000aea014610254578063556f0dc71461026757806362ad1b831461026f57806370a082311461028457600080fd5b806306e485381461017857806306fdde031461019657806307546172146101ab578063095ea7b3146101d657806318160ddd146101f957806323b872dd1461020b575b600080fd5b6101806103c2565b60405161018d91906119b5565b60405180910390f35b61019e610424565b60405161018d9190611a4f565b6009546101be906001600160a01b031681565b6040516001600160a01b03909116815260200161018d565b6101e96101e4366004611a7a565b6104ad565b604051901515815260200161018d565b6001545b60405190815260200161018d565b6101e9610219366004611aa6565b6104c5565b6101fd7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b6040516012815260200161018d565b6101e9610262366004611b30565b61066d565b600a546101fd565b61028261027d366004611b8c565b610774565b005b6101fd610292366004611c2b565b6001600160a01b031660009081526020819052604090205490565b6101fd6102bb366004611c2b565b600c6020526000908152604090205481565b6102826102db366004611c2b565b61081d565b61019e61093b565b6102826102f6366004611b30565b61094a565b6101e9610309366004611a7a565b6109a4565b61028261031c366004611c48565b610a87565b6101e961032f366004611cbf565b610c84565b610282610342366004611cf8565b610d26565b6101fd610355366004611cbf565b6001600160a01b03918216600090815260086020908152604080832093909416825291909152205490565b6101fd600b5481565b610282610397366004611c2b565b610e13565b6102826103aa366004611cf8565b610f2f565b6102826103bd366004611d84565b610fcb565b6060600480548060200260200160405190810160405280929190818152602001828054801561041a57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116103fc575b5050505050905090565b60606002805461043390611dd0565b80601f016020809104026020016040519081016040528092919081815260200182805461045f90611dd0565b801561041a5780601f106104815761010080835404028352916020019161041a565b820191906000526020600020905b81548152906001019060200180831161048f57509395945050505050565b6000336104bb818585611077565b5060019392505050565b60006001600160a01b0383166105225760405162461bcd60e51b815260206004820181905260248201527f4552433737373a207472616e7366657220746f207a65726f206164647265737360448201526064015b60405180910390fd5b6001600160a01b0384166105835760405162461bcd60e51b815260206004820152602260248201527f4552433737373a207472616e736665722066726f6d207a65726f206164647265604482015261737360f01b6064820152608401610519565b60003390506105b481868686604051806020016040528060008152506040518060200160405280600081525061112e565b6105e0818686866040518060200160405280600081525060405180602001604052806000815250611264565b610634858261062f86604051806060016040528060298152602001612010602991396001600160a01b03808c166000908152600860209081526040808320938b16835292905220549190611386565b611077565b61066281868686604051806020016040528060008152506040518060200160405280600081525060006113c0565b506001949350505050565b6000803390506106c58182888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506040805160208101909152818152935091506115949050565b7fe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c1681878787876040516106fc959493929190611e34565b60405180910390a1604051635260769b60e11b81526001600160a01b0387169063a4c0ed3690610736908490899089908990600401611e73565b600060405180830381600087803b15801561075057600080fd5b505af1158015610764573d6000803e3d6000fd5b5060019998505050505050505050565b61077e3388610c84565b61079a5760405162461bcd60e51b815260040161051990611ea5565b6108143388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a915089908190840183828082843760009201919091525060019250611594915050565b50505050505050565b336001600160a01b03821614156108825760405162461bcd60e51b8152602060048201526024808201527f4552433737373a20617574686f72697a696e672073656c66206173206f70657260448201526330ba37b960e11b6064820152608401610519565b6001600160a01b03811660009081526005602052604090205460ff16156108d3573360009081526007602090815260408083206001600160a01b03851684529091529020805460ff19169055610902565b3360009081526006602090815260408083206001600160a01b03851684529091529020805460ff191660011790555b60405133906001600160a01b038316907ff4caeb2d6ca8932a215a353d0703c326ec2d81fc68170f320eb2ab49e9df61f990600090a350565b60606003805461043390611dd0565b61099e3333868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060408051602081019091529081529250600191506115949050565b50505050565b60006001600160a01b0383166109fc5760405162461bcd60e51b815260206004820181905260248201527f4552433737373a207472616e7366657220746f207a65726f20616464726573736044820152606401610519565b6000339050610a2d81828686604051806020016040528060008152506040518060200160405280600081525061112e565b610a59818286866040518060200160405280600081525060405180602001604052806000815250611264565b6104bb81828686604051806020016040528060008152506040518060200160405280600081525060006113c0565b42841015610acc5760405162461bcd60e51b815260206004820152601260248201527114da5919551bdad95b8e881156141254915160721b6044820152606401610519565b600b546001600160a01b0388166000908152600c6020526040812080549192610b949290917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918c918c918c9188610b2383611efc565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810188905260e0016040516020818303038152906040528051906020012060405161190160f01b8152600281019290925260228201526042902090565b6040805160008082526020820180845284905260ff88169282019290925260608101869052608081018590529192509060019060a0016020604051602081039080840390855afa158015610bec573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590610c225750886001600160a01b0316816001600160a01b0316145b610c6e5760405162461bcd60e51b815260206004820152601c60248201527f53696465546f6b656e3a20494e56414c49445f5349474e4154555245000000006044820152606401610519565b610c79898989611077565b505050505050505050565b6000816001600160a01b0316836001600160a01b03161480610cef57506001600160a01b03831660009081526005602052604090205460ff168015610cef57506001600160a01b0380831660009081526007602090815260408083209387168352929052205460ff16155b80610d1f57506001600160a01b0380831660009081526006602090815260408083209387168352929052205460ff165b9392505050565b6009546001600160a01b0316336001600160a01b031614610d955760405162461bcd60e51b815260206004820152602360248201527f53696465546f6b656e3a2043616c6c6572206973206e6f7420746865206d696e6044820152623a32b960e91b6064820152608401610519565b610e0b33878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8b01819004810282018101909252898152925089915088908190840183828082843760009201919091525061166b92505050565b505050505050565b6001600160a01b038116331415610e765760405162461bcd60e51b815260206004820152602160248201527f4552433737373a207265766f6b696e672073656c66206173206f70657261746f6044820152603960f91b6064820152608401610519565b6001600160a01b03811660009081526005602052604090205460ff1615610eca573360009081526007602090815260408083206001600160a01b03851684529091529020805460ff19166001179055610ef6565b3360009081526006602090815260408083206001600160a01b03851684529091529020805460ff191690555b60405133906001600160a01b038316907f50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa190600090a350565b610f393387610c84565b610f555760405162461bcd60e51b815260040161051990611ea5565b610e0b33878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506117b992505050565b61101b33338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250604080516020810190915290815292506117b9915050565b505050565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b6001600160a01b0382166110cd5760405162461bcd60e51b815260206004820152601f60248201527f4552433737373a20617070726f766520746f207a65726f2061646472657373006044820152606401610519565b6001600160a01b0383811660008181526008602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60405163555ddc6560e11b81526001600160a01b03861660048201527f29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe8956024820152600090731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca9060440160206040518083038186803b1580156111aa57600080fd5b505afa1580156111be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e29190611f17565b90506001600160a01b0381161561081457604051633ad5cbc160e11b81526001600160a01b038216906375ab978290611229908a908a908a908a908a908a90600401611f34565b600060405180830381600087803b15801561124357600080fd5b505af1158015611257573d6000803e3d6000fd5b5050505050505050505050565b6112a183604051806060016040528060278152602001611fe9602791396001600160a01b0388166000908152602081905260409020549190611386565b6001600160a01b0380871660009081526020819052604080822093909355908616815220546112d09084611914565b6001600160a01b0380861660008181526020819052604090819020939093559151878216918916907f06b541ddaa720db2b10a4d0cdac39b8d360425fc073085fac19bc826146779879061132990889088908890611f8e565b60405180910390a4836001600160a01b0316856001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8560405161137691815260200190565b60405180910390a3505050505050565b600081848411156113aa5760405162461bcd60e51b81526004016105199190611a4f565b5060006113b78486611fb9565b95945050505050565b60405163555ddc6560e11b81526001600160a01b03861660048201527fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b6024820152600090731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca9060440160206040518083038186803b15801561143c57600080fd5b505afa158015611450573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114749190611f17565b90506001600160a01b038116156114f0576040516223de2960e01b81526001600160a01b038216906223de29906114b9908b908b908b908b908b908b90600401611f34565b600060405180830381600087803b1580156114d357600080fd5b505af11580156114e7573d6000803e3d6000fd5b5050505061158a565b811561158a576001600160a01b0386163b1561158a5760405162461bcd60e51b815260206004820152604d60248201527f4552433737373a20746f6b656e20726563697069656e7420636f6e747261637460448201527f20686173206e6f20696d706c656d656e74657220666f7220455243373737546f60648201526c1ad95b9cd49958da5c1a595b9d609a1b608482015260a401610519565b5050505050505050565b6001600160a01b0386166115ea5760405162461bcd60e51b815260206004820152601e60248201527f4552433737373a2073656e642066726f6d207a65726f206164647265737300006044820152606401610519565b6001600160a01b0385166116405760405162461bcd60e51b815260206004820152601c60248201527f4552433737373a2073656e6420746f207a65726f2061646472657373000000006044820152606401610519565b61164e87878787878761112e565b61165c878787878787611264565b610814878787878787876113c0565b6001600160a01b0384166116c15760405162461bcd60e51b815260206004820152601c60248201527f4552433737373a206d696e7420746f207a65726f2061646472657373000000006044820152606401610519565b6001546116ce9084611914565b6001556001600160a01b0384166000908152602081905260409020546116f49084611914565b6001600160a01b0385166000908152602081905260408120919091556117219086908686868660016113c0565b836001600160a01b0316856001600160a01b03167f2fe5be0146f74c5bce36c0b80911af6c7d86ff27e89d5cfa61fc681327954e5d85858560405161176893929190611f8e565b60405180910390a36040518381526001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050505050565b6001600160a01b03841661180f5760405162461bcd60e51b815260206004820152601e60248201527f4552433737373a206275726e2066726f6d207a65726f206164647265737300006044820152606401610519565b61181e8585600086868661112e565b61185b83604051806060016040528060238152602001612039602391396001600160a01b0387166000908152602081905260409020549190611386565b6001600160a01b0385166000908152602081905260409020556001546118819084611973565b600181905550836001600160a01b0316856001600160a01b03167fa78a9be3a7b862d26933ad85fb11d80ef66b8f972d7cbba06621d583943a40988585856040516118ce93929190611f8e565b60405180910390a36040518381526000906001600160a01b038616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016117aa565b6000806119218385611fd0565b905083811015610d1f5760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606401610519565b6000610d1f83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611386565b6020808252825182820181905260009190848201906040850190845b818110156119f65783516001600160a01b0316835292840192918401916001016119d1565b50909695505050505050565b6000815180845260005b81811015611a2857602081850181015186830182015201611a0c565b81811115611a3a576000602083870101525b50601f01601f19169290920160200192915050565b602081526000610d1f6020830184611a02565b6001600160a01b0381168114611a7757600080fd5b50565b60008060408385031215611a8d57600080fd5b8235611a9881611a62565b946020939093013593505050565b600080600060608486031215611abb57600080fd5b8335611ac681611a62565b92506020840135611ad681611a62565b929592945050506040919091013590565b60008083601f840112611af957600080fd5b50813567ffffffffffffffff811115611b1157600080fd5b602083019150836020828501011115611b2957600080fd5b9250929050565b60008060008060608587031215611b4657600080fd5b8435611b5181611a62565b935060208501359250604085013567ffffffffffffffff811115611b7457600080fd5b611b8087828801611ae7565b95989497509550505050565b600080600080600080600060a0888a031215611ba757600080fd5b8735611bb281611a62565b96506020880135611bc281611a62565b955060408801359450606088013567ffffffffffffffff80821115611be657600080fd5b611bf28b838c01611ae7565b909650945060808a0135915080821115611c0b57600080fd5b50611c188a828b01611ae7565b989b979a50959850939692959293505050565b600060208284031215611c3d57600080fd5b8135610d1f81611a62565b600080600080600080600060e0888a031215611c6357600080fd5b8735611c6e81611a62565b96506020880135611c7e81611a62565b95506040880135945060608801359350608088013560ff81168114611ca257600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611cd257600080fd5b8235611cdd81611a62565b91506020830135611ced81611a62565b809150509250929050565b60008060008060008060808789031215611d1157600080fd5b8635611d1c81611a62565b955060208701359450604087013567ffffffffffffffff80821115611d4057600080fd5b611d4c8a838b01611ae7565b90965094506060890135915080821115611d6557600080fd5b50611d7289828a01611ae7565b979a9699509497509295939492505050565b600080600060408486031215611d9957600080fd5b83359250602084013567ffffffffffffffff811115611db757600080fd5b611dc386828701611ae7565b9497909650939450505050565b600181811c90821680611de457607f821691505b60208210811415611e0557634e487b7160e01b600052602260045260246000fd5b50919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0386811682528516602082015260408101849052608060608201819052600090611e689083018486611e0b565b979650505050505050565b60018060a01b0385168152836020820152606060408201526000611e9b606083018486611e0b565b9695505050505050565b60208082526021908201527f4552433737373a2063616c6c6572206973206e6f7420616e206f70657261746f6040820152603960f91b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6000600019821415611f1057611f10611ee6565b5060010190565b600060208284031215611f2957600080fd5b8151610d1f81611a62565b6001600160a01b0387811682528681166020830152851660408201526060810184905260c060808201819052600090611f6f90830185611a02565b82810360a0840152611f818185611a02565b9998505050505050505050565b838152606060208201526000611fa76060830185611a02565b8281036040840152611e9b8185611a02565b600082821015611fcb57611fcb611ee6565b500390565b60008219821115611fe357611fe3611ee6565b50019056fe4552433737373a207472616e7366657220616d6f756e7420657863656564732062616c616e63654552433737373a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654552433737373a206275726e20616d6f756e7420657863656564732062616c616e6365a26469706673582212200c7501d31bab7450e37bb23b0ea5c1f0c42fe7012b6f79c8bb3dbcf38b9af37664736f6c63430008090033a2646970667358221220d52f28fd274a083181b089c52f22af452597c167983264f252a0faface07d14264736f6c63430008090033
Deployed ByteCode
0x60806040523480156200001157600080fd5b5060043610620000465760003560e01c80632348238c146200004b57806326d9e9631462000064578063c6dbdf611462000097575b600080fd5b620000626200005c36600462000296565b620000a9565b005b6200007b6200007536600462000314565b620001a7565b6040516001600160a01b03909116815260200160405180910390f35b6000546001600160a01b03166200007b565b6000546001600160a01b0316336001600160a01b031614620000e85760405162461bcd60e51b8152600401620000df906200038f565b60405180910390fd5b6001600160a01b038116620001535760405162461bcd60e51b815260206004820152602a60248201527f5365636f6e646172793a206e6577207072696d61727920697320746865207a65604482015269726f206164647265737360b01b6064820152608401620000df565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f4101e71e974f68df5e9730cc223280b41654676bbb052cdcc735c3337e64d2d99060200160405180910390a150565b600080546001600160a01b0316336001600160a01b031614620001de5760405162461bcd60e51b8152600401620000df906200038f565b600086868686620001f76000546001600160a01b031690565b87604051620002069062000288565b620002179695949392919062000404565b604051809103906000f08015801562000234573d6000803e3d6000fd5b509050806001600160a01b03167ff57d2ded8330a4affd2fa52378069be534fe22288536537d1a1cfc061518450786868660405162000276939291906200044e565b60405180910390a29695505050505050565b6127b0806200047583390190565b600060208284031215620002a957600080fd5b81356001600160a01b0381168114620002c157600080fd5b9392505050565b60008083601f840112620002db57600080fd5b50813567ffffffffffffffff811115620002f457600080fd5b6020830191508360208285010111156200030d57600080fd5b9250929050565b6000806000806000606086880312156200032d57600080fd5b853567ffffffffffffffff808211156200034657600080fd5b6200035489838a01620002c8565b909750955060208801359150808211156200036e57600080fd5b506200037d88828901620002c8565b96999598509660400135949350505050565b6020808252602c908201527f5365636f6e646172793a2063616c6c6572206973206e6f74207468652070726960408201526b1b585c9e481858d8dbdd5b9d60a21b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6080815260006200041a60808301888a620003db565b82810360208401526200042f818789620003db565b6001600160a01b03959095166040840152505060600152949350505050565b60408152600062000464604083018587620003db565b905082602083015294935050505056fe60806040523480156200001157600080fd5b50604051620027b0380380620027b08339810160408190526200003491620005ff565b60408051600081526020808201909252855186928692916200005d916002919086019062000434565b5081516200007390600390602085019062000434565b50805162000089906004906020840190620004c3565b5060005b600454811015620000fd5760016005600060048481548110620000b457620000b462000692565b6000918252602080832091909101546001600160a01b031683528201929092526040019020805460ff191691151591909117905580620000f481620006a8565b9150506200008d565b506040516329965a1d60e01b815230600482018190527fac7fbab5f54a3ca8194167523c6753bfeb96a445279294b6125b68cce217705460248301526044820152731820a4b7618bde71dce8cdc73aab6c95905fad24906329965a1d90606401600060405180830381600087803b1580156200017857600080fd5b505af11580156200018d573d6000803e3d6000fd5b50506040516329965a1d60e01b815230600482018190527faea199e31a596269b42cdafd93407f14436db6e4cad65417994c2eb37381e05a60248301526044820152731820a4b7618bde71dce8cdc73aab6c95905fad2492506329965a1d9150606401600060405180830381600087803b1580156200020b57600080fd5b505af115801562000220573d6000803e3d6000fd5b50505050506001600160a01b038416151591506200028790505760405162461bcd60e51b815260206004820152601760248201527f53696465546f6b656e3a20456d707479204d696e74657200000000000000000060448201526064015b60405180910390fd5b6001811015620002da5760405162461bcd60e51b815260206004820152601a60248201527f53696465546f6b656e3a204772616e756c6172697479203c203100000000000060448201526064016200027e565b600980546001600160a01b0319166001600160a01b038416179055600a819055620003356200030862000343565b604051806040016040528060018152602001603160f81b8152504630620003dd60201b620010201760201c565b600b55506200070f92505050565b6060600280546200035490620006d2565b80601f01602080910402602001604051908101604052809291908181526020018280546200038290620006d2565b8015620003d35780601f10620003a757610100808354040283529160200191620003d3565b820191906000526020600020905b815481529060010190602001808311620003b557829003601f168201915b5050505050905090565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b8280546200044290620006d2565b90600052602060002090601f016020900481019282620004665760008555620004b1565b82601f106200048157805160ff1916838001178555620004b1565b82800160010185558215620004b1579182015b82811115620004b157825182559160200191906001019062000494565b50620004bf9291506200051b565b5090565b828054828255906000526020600020908101928215620004b1579160200282015b82811115620004b157825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620004e4565b5b80821115620004bf57600081556001016200051c565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200055a57600080fd5b81516001600160401b038082111562000577576200057762000532565b604051601f8301601f19908116603f01168101908282118183101715620005a257620005a262000532565b81604052838152602092508683858801011115620005bf57600080fd5b600091505b83821015620005e35785820183015181830184015290820190620005c4565b83821115620005f55760008385830101525b9695505050505050565b600080600080608085870312156200061657600080fd5b84516001600160401b03808211156200062e57600080fd5b6200063c8883890162000548565b955060208701519150808211156200065357600080fd5b50620006628782880162000548565b604087015190945090506001600160a01b03811681146200068257600080fd5b6060959095015193969295505050565b634e487b7160e01b600052603260045260246000fd5b6000600019821415620006cb57634e487b7160e01b600052601160045260246000fd5b5060010190565b600181811c90821680620006e757607f821691505b602082108114156200070957634e487b7160e01b600052602260045260246000fd5b50919050565b612091806200071f6000396000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c80637ecebe00116100de578063d95b637111610097578063f698da2511610071578063f698da2514610380578063fad8b32a14610389578063fc673c4f1461039c578063fe9d9303146103af57600080fd5b8063d95b637114610321578063dcdc7dd014610334578063dd62ed3e1461034757600080fd5b80637ecebe00146102ad578063959b8c3f146102cd57806395d89b41146102e05780639bd9bbc6146102e8578063a9059cbb146102fb578063d505accf1461030e57600080fd5b806330adf81f1161013057806330adf81f1461021e578063313ce567146102455780634000aea014610254578063556f0dc71461026757806362ad1b831461026f57806370a082311461028457600080fd5b806306e485381461017857806306fdde031461019657806307546172146101ab578063095ea7b3146101d657806318160ddd146101f957806323b872dd1461020b575b600080fd5b6101806103c2565b60405161018d91906119b5565b60405180910390f35b61019e610424565b60405161018d9190611a4f565b6009546101be906001600160a01b031681565b6040516001600160a01b03909116815260200161018d565b6101e96101e4366004611a7a565b6104ad565b604051901515815260200161018d565b6001545b60405190815260200161018d565b6101e9610219366004611aa6565b6104c5565b6101fd7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b6040516012815260200161018d565b6101e9610262366004611b30565b61066d565b600a546101fd565b61028261027d366004611b8c565b610774565b005b6101fd610292366004611c2b565b6001600160a01b031660009081526020819052604090205490565b6101fd6102bb366004611c2b565b600c6020526000908152604090205481565b6102826102db366004611c2b565b61081d565b61019e61093b565b6102826102f6366004611b30565b61094a565b6101e9610309366004611a7a565b6109a4565b61028261031c366004611c48565b610a87565b6101e961032f366004611cbf565b610c84565b610282610342366004611cf8565b610d26565b6101fd610355366004611cbf565b6001600160a01b03918216600090815260086020908152604080832093909416825291909152205490565b6101fd600b5481565b610282610397366004611c2b565b610e13565b6102826103aa366004611cf8565b610f2f565b6102826103bd366004611d84565b610fcb565b6060600480548060200260200160405190810160405280929190818152602001828054801561041a57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116103fc575b5050505050905090565b60606002805461043390611dd0565b80601f016020809104026020016040519081016040528092919081815260200182805461045f90611dd0565b801561041a5780601f106104815761010080835404028352916020019161041a565b820191906000526020600020905b81548152906001019060200180831161048f57509395945050505050565b6000336104bb818585611077565b5060019392505050565b60006001600160a01b0383166105225760405162461bcd60e51b815260206004820181905260248201527f4552433737373a207472616e7366657220746f207a65726f206164647265737360448201526064015b60405180910390fd5b6001600160a01b0384166105835760405162461bcd60e51b815260206004820152602260248201527f4552433737373a207472616e736665722066726f6d207a65726f206164647265604482015261737360f01b6064820152608401610519565b60003390506105b481868686604051806020016040528060008152506040518060200160405280600081525061112e565b6105e0818686866040518060200160405280600081525060405180602001604052806000815250611264565b610634858261062f86604051806060016040528060298152602001612010602991396001600160a01b03808c166000908152600860209081526040808320938b16835292905220549190611386565b611077565b61066281868686604051806020016040528060008152506040518060200160405280600081525060006113c0565b506001949350505050565b6000803390506106c58182888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506040805160208101909152818152935091506115949050565b7fe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c1681878787876040516106fc959493929190611e34565b60405180910390a1604051635260769b60e11b81526001600160a01b0387169063a4c0ed3690610736908490899089908990600401611e73565b600060405180830381600087803b15801561075057600080fd5b505af1158015610764573d6000803e3d6000fd5b5060019998505050505050505050565b61077e3388610c84565b61079a5760405162461bcd60e51b815260040161051990611ea5565b6108143388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a915089908190840183828082843760009201919091525060019250611594915050565b50505050505050565b336001600160a01b03821614156108825760405162461bcd60e51b8152602060048201526024808201527f4552433737373a20617574686f72697a696e672073656c66206173206f70657260448201526330ba37b960e11b6064820152608401610519565b6001600160a01b03811660009081526005602052604090205460ff16156108d3573360009081526007602090815260408083206001600160a01b03851684529091529020805460ff19169055610902565b3360009081526006602090815260408083206001600160a01b03851684529091529020805460ff191660011790555b60405133906001600160a01b038316907ff4caeb2d6ca8932a215a353d0703c326ec2d81fc68170f320eb2ab49e9df61f990600090a350565b60606003805461043390611dd0565b61099e3333868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060408051602081019091529081529250600191506115949050565b50505050565b60006001600160a01b0383166109fc5760405162461bcd60e51b815260206004820181905260248201527f4552433737373a207472616e7366657220746f207a65726f20616464726573736044820152606401610519565b6000339050610a2d81828686604051806020016040528060008152506040518060200160405280600081525061112e565b610a59818286866040518060200160405280600081525060405180602001604052806000815250611264565b6104bb81828686604051806020016040528060008152506040518060200160405280600081525060006113c0565b42841015610acc5760405162461bcd60e51b815260206004820152601260248201527114da5919551bdad95b8e881156141254915160721b6044820152606401610519565b600b546001600160a01b0388166000908152600c6020526040812080549192610b949290917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918c918c918c9188610b2383611efc565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810188905260e0016040516020818303038152906040528051906020012060405161190160f01b8152600281019290925260228201526042902090565b6040805160008082526020820180845284905260ff88169282019290925260608101869052608081018590529192509060019060a0016020604051602081039080840390855afa158015610bec573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590610c225750886001600160a01b0316816001600160a01b0316145b610c6e5760405162461bcd60e51b815260206004820152601c60248201527f53696465546f6b656e3a20494e56414c49445f5349474e4154555245000000006044820152606401610519565b610c79898989611077565b505050505050505050565b6000816001600160a01b0316836001600160a01b03161480610cef57506001600160a01b03831660009081526005602052604090205460ff168015610cef57506001600160a01b0380831660009081526007602090815260408083209387168352929052205460ff16155b80610d1f57506001600160a01b0380831660009081526006602090815260408083209387168352929052205460ff165b9392505050565b6009546001600160a01b0316336001600160a01b031614610d955760405162461bcd60e51b815260206004820152602360248201527f53696465546f6b656e3a2043616c6c6572206973206e6f7420746865206d696e6044820152623a32b960e91b6064820152608401610519565b610e0b33878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8b01819004810282018101909252898152925089915088908190840183828082843760009201919091525061166b92505050565b505050505050565b6001600160a01b038116331415610e765760405162461bcd60e51b815260206004820152602160248201527f4552433737373a207265766f6b696e672073656c66206173206f70657261746f6044820152603960f91b6064820152608401610519565b6001600160a01b03811660009081526005602052604090205460ff1615610eca573360009081526007602090815260408083206001600160a01b03851684529091529020805460ff19166001179055610ef6565b3360009081526006602090815260408083206001600160a01b03851684529091529020805460ff191690555b60405133906001600160a01b038316907f50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa190600090a350565b610f393387610c84565b610f555760405162461bcd60e51b815260040161051990611ea5565b610e0b33878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506117b992505050565b61101b33338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250604080516020810190915290815292506117b9915050565b505050565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b6001600160a01b0382166110cd5760405162461bcd60e51b815260206004820152601f60248201527f4552433737373a20617070726f766520746f207a65726f2061646472657373006044820152606401610519565b6001600160a01b0383811660008181526008602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60405163555ddc6560e11b81526001600160a01b03861660048201527f29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe8956024820152600090731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca9060440160206040518083038186803b1580156111aa57600080fd5b505afa1580156111be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e29190611f17565b90506001600160a01b0381161561081457604051633ad5cbc160e11b81526001600160a01b038216906375ab978290611229908a908a908a908a908a908a90600401611f34565b600060405180830381600087803b15801561124357600080fd5b505af1158015611257573d6000803e3d6000fd5b5050505050505050505050565b6112a183604051806060016040528060278152602001611fe9602791396001600160a01b0388166000908152602081905260409020549190611386565b6001600160a01b0380871660009081526020819052604080822093909355908616815220546112d09084611914565b6001600160a01b0380861660008181526020819052604090819020939093559151878216918916907f06b541ddaa720db2b10a4d0cdac39b8d360425fc073085fac19bc826146779879061132990889088908890611f8e565b60405180910390a4836001600160a01b0316856001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8560405161137691815260200190565b60405180910390a3505050505050565b600081848411156113aa5760405162461bcd60e51b81526004016105199190611a4f565b5060006113b78486611fb9565b95945050505050565b60405163555ddc6560e11b81526001600160a01b03861660048201527fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b6024820152600090731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca9060440160206040518083038186803b15801561143c57600080fd5b505afa158015611450573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114749190611f17565b90506001600160a01b038116156114f0576040516223de2960e01b81526001600160a01b038216906223de29906114b9908b908b908b908b908b908b90600401611f34565b600060405180830381600087803b1580156114d357600080fd5b505af11580156114e7573d6000803e3d6000fd5b5050505061158a565b811561158a576001600160a01b0386163b1561158a5760405162461bcd60e51b815260206004820152604d60248201527f4552433737373a20746f6b656e20726563697069656e7420636f6e747261637460448201527f20686173206e6f20696d706c656d656e74657220666f7220455243373737546f60648201526c1ad95b9cd49958da5c1a595b9d609a1b608482015260a401610519565b5050505050505050565b6001600160a01b0386166115ea5760405162461bcd60e51b815260206004820152601e60248201527f4552433737373a2073656e642066726f6d207a65726f206164647265737300006044820152606401610519565b6001600160a01b0385166116405760405162461bcd60e51b815260206004820152601c60248201527f4552433737373a2073656e6420746f207a65726f2061646472657373000000006044820152606401610519565b61164e87878787878761112e565b61165c878787878787611264565b610814878787878787876113c0565b6001600160a01b0384166116c15760405162461bcd60e51b815260206004820152601c60248201527f4552433737373a206d696e7420746f207a65726f2061646472657373000000006044820152606401610519565b6001546116ce9084611914565b6001556001600160a01b0384166000908152602081905260409020546116f49084611914565b6001600160a01b0385166000908152602081905260408120919091556117219086908686868660016113c0565b836001600160a01b0316856001600160a01b03167f2fe5be0146f74c5bce36c0b80911af6c7d86ff27e89d5cfa61fc681327954e5d85858560405161176893929190611f8e565b60405180910390a36040518381526001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050505050565b6001600160a01b03841661180f5760405162461bcd60e51b815260206004820152601e60248201527f4552433737373a206275726e2066726f6d207a65726f206164647265737300006044820152606401610519565b61181e8585600086868661112e565b61185b83604051806060016040528060238152602001612039602391396001600160a01b0387166000908152602081905260409020549190611386565b6001600160a01b0385166000908152602081905260409020556001546118819084611973565b600181905550836001600160a01b0316856001600160a01b03167fa78a9be3a7b862d26933ad85fb11d80ef66b8f972d7cbba06621d583943a40988585856040516118ce93929190611f8e565b60405180910390a36040518381526000906001600160a01b038616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016117aa565b6000806119218385611fd0565b905083811015610d1f5760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606401610519565b6000610d1f83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611386565b6020808252825182820181905260009190848201906040850190845b818110156119f65783516001600160a01b0316835292840192918401916001016119d1565b50909695505050505050565b6000815180845260005b81811015611a2857602081850181015186830182015201611a0c565b81811115611a3a576000602083870101525b50601f01601f19169290920160200192915050565b602081526000610d1f6020830184611a02565b6001600160a01b0381168114611a7757600080fd5b50565b60008060408385031215611a8d57600080fd5b8235611a9881611a62565b946020939093013593505050565b600080600060608486031215611abb57600080fd5b8335611ac681611a62565b92506020840135611ad681611a62565b929592945050506040919091013590565b60008083601f840112611af957600080fd5b50813567ffffffffffffffff811115611b1157600080fd5b602083019150836020828501011115611b2957600080fd5b9250929050565b60008060008060608587031215611b4657600080fd5b8435611b5181611a62565b935060208501359250604085013567ffffffffffffffff811115611b7457600080fd5b611b8087828801611ae7565b95989497509550505050565b600080600080600080600060a0888a031215611ba757600080fd5b8735611bb281611a62565b96506020880135611bc281611a62565b955060408801359450606088013567ffffffffffffffff80821115611be657600080fd5b611bf28b838c01611ae7565b909650945060808a0135915080821115611c0b57600080fd5b50611c188a828b01611ae7565b989b979a50959850939692959293505050565b600060208284031215611c3d57600080fd5b8135610d1f81611a62565b600080600080600080600060e0888a031215611c6357600080fd5b8735611c6e81611a62565b96506020880135611c7e81611a62565b95506040880135945060608801359350608088013560ff81168114611ca257600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611cd257600080fd5b8235611cdd81611a62565b91506020830135611ced81611a62565b809150509250929050565b60008060008060008060808789031215611d1157600080fd5b8635611d1c81611a62565b955060208701359450604087013567ffffffffffffffff80821115611d4057600080fd5b611d4c8a838b01611ae7565b90965094506060890135915080821115611d6557600080fd5b50611d7289828a01611ae7565b979a9699509497509295939492505050565b600080600060408486031215611d9957600080fd5b83359250602084013567ffffffffffffffff811115611db757600080fd5b611dc386828701611ae7565b9497909650939450505050565b600181811c90821680611de457607f821691505b60208210811415611e0557634e487b7160e01b600052602260045260246000fd5b50919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0386811682528516602082015260408101849052608060608201819052600090611e689083018486611e0b565b979650505050505050565b60018060a01b0385168152836020820152606060408201526000611e9b606083018486611e0b565b9695505050505050565b60208082526021908201527f4552433737373a2063616c6c6572206973206e6f7420616e206f70657261746f6040820152603960f91b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6000600019821415611f1057611f10611ee6565b5060010190565b600060208284031215611f2957600080fd5b8151610d1f81611a62565b6001600160a01b0387811682528681166020830152851660408201526060810184905260c060808201819052600090611f6f90830185611a02565b82810360a0840152611f818185611a02565b9998505050505050505050565b838152606060208201526000611fa76060830185611a02565b8281036040840152611e9b8185611a02565b600082821015611fcb57611fcb611ee6565b500390565b60008219821115611fe357611fe3611ee6565b50019056fe4552433737373a207472616e7366657220616d6f756e7420657863656564732062616c616e63654552433737373a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654552433737373a206275726e20616d6f756e7420657863656564732062616c616e6365a26469706673582212200c7501d31bab7450e37bb23b0ea5c1f0c42fe7012b6f79c8bb3dbcf38b9af37664736f6c63430008090033a2646970667358221220d52f28fd274a083181b089c52f22af452597c167983264f252a0faface07d14264736f6c63430008090033