Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Token
- Optimization enabled
- true
- Compiler version
- v0.8.18+commit.87f61d96
- Optimization runs
- 20000
- EVM Version
- default
- Verified at
- 2024-02-07T08:49:18.947617Z
contracts/token/Token.sol
// SPDX-License-Identifier: GPL-3.0-or-later
// Based on ERC20 implementation of @openzeppelin/contracts (v4.5.0):
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.5.0/contracts/token/ERC20/ERC20.sol
pragma solidity ^0.8.0;
import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {MultiCurrency} from "./MultiCurrency.sol";
import {IToken} from "./IToken.sol";
/// @title MultiCurrency Predeploy Contract
/// @author Acala Developers
/// @notice You can use this predeploy contract to call currencies pallet
/// @dev This contracts will interact with currencies pallet
contract Token is IToken {
using SafeMath for uint256;
mapping(address => mapping(address => uint256)) private _allowances;
/// @notice Get the name of the token.
/// @return Returns the name of the token.
function name() public view returns (string memory) {
return MultiCurrency.name();
}
/// @notice Get the symbol of the token, usually a shorter version of the name.
/// @return Returns the symbol of the token.
function symbol() public view returns (string memory) {
return MultiCurrency.symbol();
}
/// @notice Get the number of decimals used to get its user representation.
/// @return Returns the number of decimals.
function decimals() public view returns (uint8) {
return MultiCurrency.decimals();
}
/// @notice Get the amount of tokens in existence.
/// @return Returns amount of tokens in existence.
function totalSupply() public view override returns (uint256) {
return MultiCurrency.totalSupply();
}
/// @notice Get the amount of tokens owned by `account`.
/// @param account The specified user.
/// @return Returns the amount of tokens owned by `account`.
function balanceOf(address account) public view override returns (uint256) {
return MultiCurrency.balanceOf(account);
}
/// @notice Moves `amount` tokens from the caller's account to `to`.
/// @dev It'll emit an {Transfer} event. The caller must have a balance of at least `amount`.
/// @param to The dest address, it cannot be the zero address.
/// @param amount The transfer amount.
/// @return Returns a boolean value indicating whether the operation succeeded.
function transfer(
address to,
uint256 amount
) public override returns (bool) {
address owner = msg.sender;
_transfer(owner, to, amount);
return true;
}
/// @notice Get the remaining number of tokens that `spender` will be allowed to spend.
/// @param owner The owner address.
/// @param spender The spender address.
/// @return Returns the remaining number of tokens.
/// The `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default.
function allowance(
address owner,
address spender
) public view override returns (uint256) {
return _allowances[owner][spender];
}
/// @notice Sets `amount` as the allowance of `spender` over the caller's tokens.
/// @dev It'll emit an {Approval} event.
/// If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`.
/// This is semantically equivalent to an infinite approval.
/// @param spender Approve the spender.
/// @param amount The approve amount.
/// @return Returns a boolean value indicating whether the operation succeeded.
function approve(
address spender,
uint256 amount
) public override returns (bool) {
address owner = msg.sender;
_approve(owner, spender, amount);
return true;
}
/// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism.
/// `amount` is then deducted from the caller's allowance.
/// @dev It'll emit an {Transfer} event.
/// @param from Transfer amount from the address.
/// The caller must have allowance for ``from``'s tokens of at least `amount`. It cannot be the zero address.
/// @param to Transfer amount to the address. It cannot be the zero address.
/// @param amount The transfer amount.
/// @return Returns a boolean value indicating whether the operation succeeded.
function transferFrom(
address from,
address to,
uint256 amount
) public override returns (bool) {
address spender = msg.sender;
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/// @dev Atomically increases the allowance granted to `spender` by the caller.
/// This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}.
/// Emits an {Approval} event indicating the updated allowance.
/// @param spender It cannot be the zero address.
/// @param addedValue The added value.
/// @return Returns a boolean value indicating whether the operation succeeded.
function increaseAllowance(
address spender,
uint256 addedValue
) public returns (bool) {
address owner = msg.sender;
_approve(owner, spender, _allowances[owner][spender] + addedValue);
return true;
}
/// @dev Atomically decreases the allowance granted to `spender` by the caller.
/// This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}.
/// Emits an {Approval} event indicating the updated allowance.
/// @param spender must have allowance for the caller of at least `subtractedValue`. It cannot be the zero address.
/// @param subtractedValue The subtracted value.
/// @return Returns a boolean value indicating whether the operation succeeded.
function decreaseAllowance(
address spender,
uint256 subtractedValue
) public returns (bool) {
address owner = msg.sender;
uint256 currentAllowance = _allowances[owner][spender];
require(
currentAllowance >= subtractedValue,
"ERC20: decreased allowance below zero"
);
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/// @inheritdoc IToken
function transferToAccountId32(
bytes32 dest,
uint256 amount
) public override returns (bool) {
address from = msg.sender;
require(
dest !=
0x0000000000000000000000000000000000000000000000000000000000000000,
"ERC20: transfer to the zero AccountId32"
);
MultiCurrency.transferToAccountId(from, dest, amount);
emit TransferToAccountId32(from, dest, amount);
return true;
}
/// @dev Moves `amount` of tokens from `sender` to `recipient`.
/// This internal function is equivalent to {transfer}, and can be used to.
/// e.g. implement automatic token fees, slashing mechanisms, etc.
/// Emits a {Transfer} event.
/// @param from must have a balance of at least `amount`. It cannot be the zero address.
/// @param to It cannot be the zero address.
function _transfer(address from, address to, uint256 amount) internal {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
MultiCurrency.transfer(from, to, amount);
emit Transfer(from, to, amount);
}
/// @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
/// This internal function is equivalent to `approve`, and can be used to.
/// e.g. set automatic allowances for certain subsystems, etc.
/// Emits an {Approval} event.
/// @param owner cannot be the zero address.
/// @param spender cannot be the zero address.
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/// @dev Spend `amount` form the allowance of `owner` toward `spender`.
/// Does not update the allowance amount in case of infinite allowance.
/// Revert if not enough allowance is available.
/// Might emit an {Approval} event.
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(
currentAllowance >= amount,
"ERC20: insufficient allowance"
);
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
}
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
@openzeppelin/contracts/utils/math/SafeMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the 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) {
return a + b;
}
/**
* @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 a - b;
}
/**
* @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) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting 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 a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting 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.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* 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, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
contracts/token/IToken.sol
// SPDX-License-Identifier: GPL-3.0-or-later
// inherit on IERC20 interface of @openzeppelin/contracts (v4.5.0):
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.5.0/contracts/token/ERC20/IERC20.sol
pragma solidity ^0.8.0;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @title IToken Predeploy Contract Interface
/// @author Acala Developers
/// @notice You can use this predeploy contract to call currencies pallet
/// @dev The interface through which solidity contracts will interact with currencies pallet
interface IToken is IERC20 {
/// @notice Transfer event to AccountId32 type account.
/// @param sender The sender of the transaction.
/// @param dest The dest AccountId32 type account.
/// @param amount The transfer amount.
/// @dev This is Transfer event which transfer AccountId32 type account.
event TransferToAccountId32(
address indexed sender,
bytes32 indexed dest,
uint256 amount
);
/// @notice Moves `amount` tokens from the caller's account to `dest`, which is AccountId32 type account.
/// @dev It'll emit an {TransferToAccountId32} event. The caller must have a balance of at least `amount`.
/// @param dest The dest AccountId32 type account, it cannot be the zero AccountId32.
/// @param amount The transfer amount.
/// @return Returns a boolean value indicating whether the operation succeeded.
function transferToAccountId32(
bytes32 dest,
uint256 amount
) external returns (bool);
}
contracts/token/MultiCurrency.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.0;
/// @title MultiCurrency Predeploy Contract Library
/// @author Acala Developers
/// @notice You can use this predeploy contract to call currencies pallet
/// @dev This contracts will interact with currencies pallet
library MultiCurrency {
/// @dev The MultiCurrency precompile address.
address private constant PRECOMPILE =
address(0x0000000000000000000000000000000000000400);
function name() internal view returns (string memory) {
(bool success, bytes memory returnData) = PRECOMPILE.staticcall(
abi.encodeWithSignature("name()")
);
assembly {
if eq(success, 0) {
revert(add(returnData, 0x20), returndatasize())
}
}
return abi.decode(returnData, (string));
}
function symbol() internal view returns (string memory) {
(bool success, bytes memory returnData) = PRECOMPILE.staticcall(
abi.encodeWithSignature("symbol()")
);
assembly {
if eq(success, 0) {
revert(add(returnData, 0x20), returndatasize())
}
}
return abi.decode(returnData, (string));
}
function decimals() internal view returns (uint8) {
(bool success, bytes memory returnData) = PRECOMPILE.staticcall(
abi.encodeWithSignature("decimals()")
);
assembly {
if eq(success, 0) {
revert(add(returnData, 0x20), returndatasize())
}
}
return abi.decode(returnData, (uint8));
}
function totalSupply() internal view returns (uint256) {
(bool success, bytes memory returnData) = PRECOMPILE.staticcall(
abi.encodeWithSignature("totalSupply()")
);
assembly {
if eq(success, 0) {
revert(add(returnData, 0x20), returndatasize())
}
}
return abi.decode(returnData, (uint256));
}
function balanceOf(address account) internal view returns (uint256) {
(bool success, bytes memory returnData) = PRECOMPILE.staticcall(
abi.encodeWithSignature("balanceOf(address)", account)
);
assembly {
if eq(success, 0) {
revert(add(returnData, 0x20), returndatasize())
}
}
return abi.decode(returnData, (uint256));
}
function transfer(
address sender,
address recipient,
uint256 amount
) internal {
(bool success, bytes memory returnData) = PRECOMPILE.call(
abi.encodeWithSignature(
"transfer(address,address,uint256)",
sender,
recipient,
amount
)
);
assembly {
if eq(success, 0) {
revert(add(returnData, 0x20), returndatasize())
}
}
}
function transferToAccountId(
address sender,
bytes32 recipient,
uint256 amount
) internal {
(bool success, bytes memory returnData) = PRECOMPILE.call(
abi.encodeWithSignature(
"transferToAccountId(address,bytes32,uint256)",
sender,
recipient,
amount
)
);
assembly {
if eq(success, 0) {
revert(add(returnData, 0x20), returndatasize())
}
}
}
}
Compiler Settings
{"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":20000,"enabled":true},"libraries":{}}
Contract ABI
[{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TransferToAccountId32","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"bytes32","name":"dest","internalType":"bytes32","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"decreaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"subtractedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"increaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"addedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferToAccountId32","inputs":[{"type":"bytes32","name":"dest","internalType":"bytes32"},{"type":"uint256","name":"amount","internalType":"uint256"}]}]
Contract Creation Code
0x608060405234801561001057600080fd5b506111f1806100206000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c806370a0823111610081578063a457c2d71161005b578063a457c2d71461019e578063a9059cbb146101b1578063dd62ed3e146101c457600080fd5b806370a0823114610170578063871069c01461018357806395d89b411461019657600080fd5b806323b872dd116100b257806323b872dd14610130578063313ce56714610143578063395093511461015d57600080fd5b806306fdde03146100d9578063095ea7b3146100f757806318160ddd1461011a575b600080fd5b6100e1610208565b6040516100ee9190610ed8565b60405180910390f35b61010a610105366004610f52565b610217565b60405190151581526020016100ee565b610122610231565b6040519081526020016100ee565b61010a61013e366004610f7c565b61023b565b61014b61025f565b60405160ff90911681526020016100ee565b61010a61016b366004610f52565b610269565b61012261017e366004610fb8565b6102b3565b61010a610191366004610fda565b6102be565b6100e16103bb565b61010a6101ac366004610f52565b6103c5565b61010a6101bf366004610f52565b610494565b6101226101d2366004610ffc565b73ffffffffffffffffffffffffffffffffffffffff91821660009081526020818152604080832093909416825291909152205490565b60606102126104a2565b905090565b60003361022581858561057d565b60019150505b92915050565b600061021261072f565b600033610249858285610802565b6102548585856108d7565b506001949350505050565b6000610212610a87565b3360008181526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061022590829086906102ae90879061102f565b61057d565b600061022b82610b5a565b600033838203610355576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f45524332303a207472616e7366657220746f20746865207a65726f204163636f60448201527f756e74496433320000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610360818585610c76565b838173ffffffffffffffffffffffffffffffffffffffff167f1d17b5770b13229fb9a0fbb368edadb0cd26837679bf04920d26031ad8fd6bdc856040516103a991815260200190565b60405180910390a35060019392505050565b6060610212610d8b565b3360008181526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610487576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161034c565b610254828686840361057d565b6000336102258185856108d7565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060916000918291610400916105109190611069565b600060405180830381855afa9150503d806000811461054b576040519150601f19603f3d011682016040523d82523d6000602084013e610550565b606091505b50909250905081610562573d60208201fd5b8080602001905181019061057691906110b4565b9250505090565b73ffffffffffffffffffffffffffffffffffffffff831661061f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161034c565b73ffffffffffffffffffffffffffffffffffffffff82166106c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161034c565b73ffffffffffffffffffffffffffffffffffffffff8381166000818152602081815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f18160ddd000000000000000000000000000000000000000000000000000000001790529051600091829182916104009161079c9190611069565b600060405180830381855afa9150503d80600081146107d7576040519150601f19603f3d011682016040523d82523d6000602084013e6107dc565b606091505b509092509050816107ee573d60208201fd5b80806020019051810190610576919061117f565b73ffffffffffffffffffffffffffffffffffffffff838116600090815260208181526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146108d157818110156108c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161034c565b6108d1848484840361057d565b50505050565b73ffffffffffffffffffffffffffffffffffffffff831661097a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161034c565b73ffffffffffffffffffffffffffffffffffffffff8216610a1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161034c565b610a28838383610df9565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161072291815260200190565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290516000918291829161040091610af49190611069565b600060405180830381855afa9150503d8060008114610b2f576040519150601f19603f3d011682016040523d82523d6000602084013e610b34565b606091505b50909250905081610b46573d60208201fd5b808060200190518101906105769190611198565b60405173ffffffffffffffffffffffffffffffffffffffff821660248201526000908190819061040090604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f70a082310000000000000000000000000000000000000000000000000000000017905251610c089190611069565b600060405180830381855afa9150503d8060008114610c43576040519150601f19603f3d011682016040523d82523d6000602084013e610c48565b606091505b50909250905081610c5a573d60208201fd5b80806020019051810190610c6e919061117f565b949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff841660248201526044810183905260648101829052600090819061040090608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f895904980000000000000000000000000000000000000000000000000000000017905251610d309190611069565b6000604051808303816000865af19150503d8060008114610d6d576040519150601f19603f3d011682016040523d82523d6000602084013e610d72565b606091505b50909250905081610d84573d60208201fd5b5050505050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060916000918291610400916105109190611069565b60405173ffffffffffffffffffffffffffffffffffffffff84811660248301528316604482015260648101829052600090819061040090608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fbeabacc80000000000000000000000000000000000000000000000000000000017905251610d309190611069565b60005b83811015610ecf578181015183820152602001610eb7565b50506000910152565b6020815260008251806020840152610ef7816040850160208701610eb4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610f4d57600080fd5b919050565b60008060408385031215610f6557600080fd5b610f6e83610f29565b946020939093013593505050565b600080600060608486031215610f9157600080fd5b610f9a84610f29565b9250610fa860208501610f29565b9150604084013590509250925092565b600060208284031215610fca57600080fd5b610fd382610f29565b9392505050565b60008060408385031215610fed57600080fd5b50508035926020909101359150565b6000806040838503121561100f57600080fd5b61101883610f29565b915061102660208401610f29565b90509250929050565b8082018082111561022b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000825161107b818460208701610eb4565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156110c657600080fd5b815167ffffffffffffffff808211156110de57600080fd5b818401915084601f8301126110f257600080fd5b81518181111561110457611104611085565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561114a5761114a611085565b8160405282815287602084870101111561116357600080fd5b611174836020830160208801610eb4565b979650505050505050565b60006020828403121561119157600080fd5b5051919050565b6000602082840312156111aa57600080fd5b815160ff81168114610fd357600080fdfea2646970667358221220054e18bc0b3f0a07464c0663a4015c3aa60d5e66cf648752fbf056e6eeefc5e864736f6c63430008120033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100d45760003560e01c806370a0823111610081578063a457c2d71161005b578063a457c2d71461019e578063a9059cbb146101b1578063dd62ed3e146101c457600080fd5b806370a0823114610170578063871069c01461018357806395d89b411461019657600080fd5b806323b872dd116100b257806323b872dd14610130578063313ce56714610143578063395093511461015d57600080fd5b806306fdde03146100d9578063095ea7b3146100f757806318160ddd1461011a575b600080fd5b6100e1610208565b6040516100ee9190610ed8565b60405180910390f35b61010a610105366004610f52565b610217565b60405190151581526020016100ee565b610122610231565b6040519081526020016100ee565b61010a61013e366004610f7c565b61023b565b61014b61025f565b60405160ff90911681526020016100ee565b61010a61016b366004610f52565b610269565b61012261017e366004610fb8565b6102b3565b61010a610191366004610fda565b6102be565b6100e16103bb565b61010a6101ac366004610f52565b6103c5565b61010a6101bf366004610f52565b610494565b6101226101d2366004610ffc565b73ffffffffffffffffffffffffffffffffffffffff91821660009081526020818152604080832093909416825291909152205490565b60606102126104a2565b905090565b60003361022581858561057d565b60019150505b92915050565b600061021261072f565b600033610249858285610802565b6102548585856108d7565b506001949350505050565b6000610212610a87565b3360008181526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061022590829086906102ae90879061102f565b61057d565b600061022b82610b5a565b600033838203610355576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f45524332303a207472616e7366657220746f20746865207a65726f204163636f60448201527f756e74496433320000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610360818585610c76565b838173ffffffffffffffffffffffffffffffffffffffff167f1d17b5770b13229fb9a0fbb368edadb0cd26837679bf04920d26031ad8fd6bdc856040516103a991815260200190565b60405180910390a35060019392505050565b6060610212610d8b565b3360008181526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610487576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161034c565b610254828686840361057d565b6000336102258185856108d7565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060916000918291610400916105109190611069565b600060405180830381855afa9150503d806000811461054b576040519150601f19603f3d011682016040523d82523d6000602084013e610550565b606091505b50909250905081610562573d60208201fd5b8080602001905181019061057691906110b4565b9250505090565b73ffffffffffffffffffffffffffffffffffffffff831661061f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161034c565b73ffffffffffffffffffffffffffffffffffffffff82166106c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161034c565b73ffffffffffffffffffffffffffffffffffffffff8381166000818152602081815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f18160ddd000000000000000000000000000000000000000000000000000000001790529051600091829182916104009161079c9190611069565b600060405180830381855afa9150503d80600081146107d7576040519150601f19603f3d011682016040523d82523d6000602084013e6107dc565b606091505b509092509050816107ee573d60208201fd5b80806020019051810190610576919061117f565b73ffffffffffffffffffffffffffffffffffffffff838116600090815260208181526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146108d157818110156108c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161034c565b6108d1848484840361057d565b50505050565b73ffffffffffffffffffffffffffffffffffffffff831661097a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161034c565b73ffffffffffffffffffffffffffffffffffffffff8216610a1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161034c565b610a28838383610df9565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161072291815260200190565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290516000918291829161040091610af49190611069565b600060405180830381855afa9150503d8060008114610b2f576040519150601f19603f3d011682016040523d82523d6000602084013e610b34565b606091505b50909250905081610b46573d60208201fd5b808060200190518101906105769190611198565b60405173ffffffffffffffffffffffffffffffffffffffff821660248201526000908190819061040090604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f70a082310000000000000000000000000000000000000000000000000000000017905251610c089190611069565b600060405180830381855afa9150503d8060008114610c43576040519150601f19603f3d011682016040523d82523d6000602084013e610c48565b606091505b50909250905081610c5a573d60208201fd5b80806020019051810190610c6e919061117f565b949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff841660248201526044810183905260648101829052600090819061040090608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f895904980000000000000000000000000000000000000000000000000000000017905251610d309190611069565b6000604051808303816000865af19150503d8060008114610d6d576040519150601f19603f3d011682016040523d82523d6000602084013e610d72565b606091505b50909250905081610d84573d60208201fd5b5050505050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060916000918291610400916105109190611069565b60405173ffffffffffffffffffffffffffffffffffffffff84811660248301528316604482015260648101829052600090819061040090608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fbeabacc80000000000000000000000000000000000000000000000000000000017905251610d309190611069565b60005b83811015610ecf578181015183820152602001610eb7565b50506000910152565b6020815260008251806020840152610ef7816040850160208701610eb4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610f4d57600080fd5b919050565b60008060408385031215610f6557600080fd5b610f6e83610f29565b946020939093013593505050565b600080600060608486031215610f9157600080fd5b610f9a84610f29565b9250610fa860208501610f29565b9150604084013590509250925092565b600060208284031215610fca57600080fd5b610fd382610f29565b9392505050565b60008060408385031215610fed57600080fd5b50508035926020909101359150565b6000806040838503121561100f57600080fd5b61101883610f29565b915061102660208401610f29565b90509250929050565b8082018082111561022b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000825161107b818460208701610eb4565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156110c657600080fd5b815167ffffffffffffffff808211156110de57600080fd5b818401915084601f8301126110f257600080fd5b81518181111561110457611104611085565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561114a5761114a611085565b8160405282815287602084870101111561116357600080fd5b611174836020830160208801610eb4565b979650505050505050565b60006020828403121561119157600080fd5b5051919050565b6000602082840312156111aa57600080fd5b815160ff81168114610fd357600080fdfea2646970667358221220054e18bc0b3f0a07464c0663a4015c3aa60d5e66cf648752fbf056e6eeefc5e864736f6c63430008120033