ETH Price: $2,337.78 (-1.32%)

Contract

0xDe9b911A2C3984bA956ae2415A3E938aaC840e13

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Sponsored

Transaction Hash
Method
Block
From
To
0x60a06040566556772022-12-28 13:24:13623 days ago1672233853IN
 Create: Shares
0 ETH0.0018186836840.001

View more zero value Internal Transactions in Advanced View mode

Advanced mode:

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Shares

Compiler Version
v0.8.12+commit.f00d7308

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license
File 1 of 12 : Shares.sol
/**
* SPDX-License-Identifier: LicenseRef-Aktionariat
*
* MIT License with Automated License Fee Payments
*
* Copyright (c) 2020 Aktionariat AG (aktionariat.com)
*
* Permission is hereby granted to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* - The above copyright notice and this permission notice shall be included in
*   all copies or substantial portions of the Software.
* - All automated license fee payments integrated into this and related Software
*   are preserved.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
pragma solidity ^0.8.0;

import "../ERC20/ERC20Named.sol";
import "../ERC20/ERC20PermitLight.sol";
import "../ERC20/IERC677Receiver.sol";
import "../recovery/ERC20Recoverable.sol";
import "../shares/IShares.sol";

/**
 * @title CompanyName AG Shares
 * @author Luzius Meisser, [email protected]
 *
 * These tokens represent ledger-based securities according to article 973d of the Swiss Code of Obligations.
 * This smart contract serves as an ownership registry, enabling the token holders to register them as
 * shareholders in the issuer's shareholder registry. This is equivalent to the traditional system
 * of having physical share certificates kept at home by the shareholders and a shareholder registry run by
 * the company. Just like with physical certificates, the owners of the tokens are the owners of the shares.
 * However, in order to exercise their rights (for example receive a dividend), shareholders must register
 * themselves. For example, in case the company pays out a dividend to a previous shareholder because
 * the current shareholder did not register, the company cannot be held liable for paying the dividend to
 * the "wrong" shareholder. In relation to the company, only the registered shareholders count as such.
 */
contract Shares is ERC20Recoverable, ERC20Named, ERC20PermitLight, IShares{

    // Version history:
    // 1: everything before 2022-07-19
    // 2: added mintMany and mintManyAndCall, added VERSION field
    // 3: added permit
    uint8 public constant VERSION = 3;

    string public terms;

    uint256 public override totalShares; // total number of shares, maybe not all tokenized
    uint256 public invalidTokens;

    event Announcement(string message);
    event TokensDeclaredInvalid(address indexed holder, uint256 amount, string message);
    event ChangeTerms(string terms);
    event ChangeTotalShares(uint256 total);

    constructor(
        string memory _symbol,
        string memory _name,
        string memory _terms,
        uint256 _totalShares,
        address _owner,
        IRecoveryHub _recoveryHub
    )
        ERC20Named(_symbol, _name, 0, _owner) 
        ERC20Recoverable(_recoveryHub)
        ERC20PermitLight()
    {
        totalShares = _totalShares;
        terms = _terms;
        invalidTokens = 0;
        _recoveryHub.setRecoverable(false); 
    }

    function setTerms(string memory _terms) external onlyOwner {
        terms = _terms;
        emit ChangeTerms(_terms);
    }

    /**
     * Declares the number of total shares, including those that have not been tokenized and those
     * that are held by the company itself. This number can be substiantially higher than totalSupply()
     * in case not all shares have been tokenized. Also, it can be lower than totalSupply() in case some
     * tokens have become invalid.
     */
    function setTotalShares(uint256 _newTotalShares) external onlyOwner() {
        require(_newTotalShares >= totalValidSupply(), "below supply");
        totalShares = _newTotalShares;
        emit ChangeTotalShares(_newTotalShares);
    }

    /**
     * Allows the issuer to make public announcements that are visible on the blockchain.
     */
    function announcement(string calldata message) external onlyOwner() {
        emit Announcement(message);
    }

    /**
     * See parent method for collateral requirements.
     */
    function setCustomClaimCollateral(IERC20 collateral, uint256 rate) external onlyOwner() {
        super._setCustomClaimCollateral(collateral, rate);
    }

    function getClaimDeleter() public override view returns (address) {
        return owner;
    }

    /**
     * Signals that the indicated tokens have been declared invalid (e.g. by a court ruling in accordance
     * with article 973g of the Swiss Code of Obligations) and got detached from
     * the underlying shares. Invalid tokens do not carry any shareholder rights any more.
     *
     * This function is purely declarative. It does not technically immobilize the affected tokens as
     * that would give the issuer too much power.
     */
    function declareInvalid(address holder, uint256 amount, string calldata message) external onlyOwner() {
        uint256 holderBalance = balanceOf(holder);
        require(amount <= holderBalance, "amount too high");
        invalidTokens += amount;
        emit TokensDeclaredInvalid(holder, amount, message);
    }

    /**
     * The total number of valid tokens in circulation. In case some tokens have been declared invalid, this
     * number might be lower than totalSupply(). Also, it will always be lower than or equal to totalShares().
     */
    function totalValidSupply() public view returns (uint256) {
        return totalSupply() - invalidTokens;
    }

    /**
     * Allows the company to tokenize shares and transfer them e.g to the draggable contract and wrap them.
     * If these shares are newly created, setTotalShares must be called first in order to adjust the total number of shares.
     */
    function mintAndCall(address shareholder, address callee, uint256 amount, bytes calldata data) external {
        mint(callee, amount);
        require(IERC677Receiver(callee).onTokenTransfer(shareholder, amount, data));
    }

    function mintManyAndCall(address[] calldata target, address callee, uint256[] calldata amount, bytes calldata data) external {
        uint256 len = target.length;
        require(len == amount.length);
        uint256 total = 0;
        for (uint256 i = 0; i<len; i++){
            total += amount[i];
        }
        mint(callee, total);
        for (uint256 i = 0; i<len; i++){
            require(IERC677Receiver(callee).onTokenTransfer(target[i], amount[i], data));
        }
    }

    function mint(address target, uint256 amount) virtual public onlyOwner {
        _mint(target, amount);
    }

    function mintMany(address[] calldata target, uint256[] calldata amount) public onlyOwner {
        uint256 len = target.length;
        require(len == amount.length);
        for (uint256 i = 0; i<len; i++){
            _mint(target[i], amount[i]);
        }
    }

    function _mint(address account, uint256 amount) internal virtual override {
        require(totalValidSupply() + amount <= totalShares, "total");
        super._mint(account, amount);
    }

    function transfer(address to, uint256 value) virtual override(ERC20Flaggable, ERC20Recoverable, IERC20) public returns (bool) {
        return super.transfer(to, value);
    }

    /**
     * Transfers _amount tokens to the company and burns them.
     * The meaning of this operation depends on the circumstances and the fate of the shares does
     * not necessarily follow the fate of the tokens. For example, the company itself might call
     * this function to implement a formal decision to destroy some of the outstanding shares.
     * Also, this function might be called by an owner to return the shares to the company and
     * get them back in another form under an according agreement (e.g. printed certificates or
     * tokens on a different blockchain). It is not recommended to call this function without
     * having agreed with the company on the further fate of the shares in question.
     */
    function burn(uint256 _amount) override external {
        _transfer(msg.sender, address(this), _amount);
        _burn(address(this), _amount);
    }

}

File 2 of 12 : ERC20Flaggable.sol
// SPDX-License-Identifier: MIT
// Copied and adjusted from OpenZeppelin
// Adjustments:
// - modifications to support ERC-677
// - removed unnecessary require statements
// - removed GSN Context
// - upgraded to 0.8 to drop SafeMath
// - let name() and symbol() be implemented by subclass
// - infinite allowance support, with 2^255 and above considered infinite
// - use upper 32 bits of balance for flags
// - add a global settings variable

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./IERC677Receiver.sol";

/**
 * @dev Implementation of the `IERC20` 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`.
 * For a generic mechanism see `ERC20Mintable`.
 *
 * *For a detailed writeup see our guide [How to implement supply
 * mechanisms](https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226).*
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an `Approval` event is emitted on calls to `transferFrom`.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard `decreaseAllowance` and `increaseAllowance`
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See `IERC20.approve`.
 */

abstract contract ERC20Flaggable is IERC20 {

    // as Documented in /doc/infiniteallowance.md
    // 0x8000000000000000000000000000000000000000000000000000000000000000
    uint256 constant private INFINITE_ALLOWANCE = 2**255;

    uint256 private constant FLAGGING_MASK = 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000;

    // Documentation of flags used by subclasses:
    // NOTE: flags denote the bit number that is being used and must be smaller than 32
    // ERC20Draggable: uint8 private constant FLAG_INDEX_VOTED = 1;
    // ERC20Recoverable: uint8 private constant FLAG_INDEX_CLAIM_PRESENT = 10;
    // ERCAllowlistable: uint8 private constant FLAG_INDEX_ALLOWLIST = 20;
    // ERCAllowlistable: uint8 private constant FLAG_INDEX_FORBIDDEN = 21;
    // ERCAllowlistable: uint8 private constant FLAG_INDEX_POWERLIST = 22;

    mapping (address => uint256) private _balances; // upper 32 bits reserved for flags

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    uint8 public override decimals;

    event NameChanged(string name, string symbol);

    constructor(uint8 _decimals) {
        decimals = _decimals;
    }

    /**
     * @dev See `IERC20.totalSupply`.
     */
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See `IERC20.balanceOf`.
     */
    function balanceOf(address account) public view override returns (uint256) {
        return uint224 (_balances [account]);
    }

    function hasFlag(address account, uint8 number) external view returns (bool) {
        return hasFlagInternal(account, number);
    }

    function setFlag(address account, uint8 index, bool value) internal {
        uint256 flagMask = 1 << (index + 224);
        uint256 balance = _balances [account];
        if ((balance & flagMask == flagMask) != value) {
            _balances [account] = balance ^ flagMask;
        }
    }

    function hasFlagInternal(address account, uint8 number) internal view returns (bool) {
        uint256 flag = 0x1 << (number + 224);
        return _balances[account] & flag == flag;
    }

    /**
     * @dev See `IERC20.transfer`.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

    /**
     * @dev See `IERC20.allowance`.
     */
    function allowance(address owner, address spender) external view override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See `IERC20.approve`.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) external override returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    /**
     * @dev See `IERC20.transferFrom`.
     *
     * Emits an `Approval` event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of `ERC20`;
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `value`.
     * - the caller must have allowance for `sender`'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) {
        _transfer(sender, recipient, amount);
        uint256 currentAllowance = _allowances[sender][msg.sender];
        if (currentAllowance < INFINITE_ALLOWANCE){
            // Only decrease the allowance if it was not set to 'infinite'
            // Documented in /doc/infiniteallowance.md
            _allowances[sender][msg.sender] = currentAllowance - amount;
        }
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to `transfer`, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a `Transfer` event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        _beforeTokenTransfer(sender, recipient, amount);
        decreaseBalance(sender, amount);
        increaseBalance(recipient, amount);
        emit Transfer(sender, recipient, amount);
    }

    // ERC-677 functionality, can be useful for swapping and wrapping tokens
    function transferAndCall(address recipient, uint amount, bytes calldata data) external virtual returns (bool) {
        return transfer (recipient, amount) 
            && IERC677Receiver (recipient).onTokenTransfer (msg.sender, amount, data);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a `Transfer` event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address recipient, uint256 amount) internal virtual {
        _beforeTokenTransfer(address(0), recipient, amount);
        _totalSupply += amount;
        increaseBalance(recipient, amount);
        emit Transfer(address(0), recipient, amount);
    }

    function increaseBalance(address recipient, uint256 amount) private {
        require(recipient != address(0x0), "0x0"); // use burn instead
        uint256 oldBalance = _balances[recipient];
        uint256 newBalance = oldBalance + amount;
        require(oldBalance & FLAGGING_MASK == newBalance & FLAGGING_MASK, "overflow");
        _balances[recipient] = newBalance;
    }

     /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a `Transfer` event with `to` set to the zero address.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        _beforeTokenTransfer(account, address(0), amount);

        _totalSupply -= amount;
        decreaseBalance(account, amount);
        emit Transfer(account, address(0), amount);
    }

    function decreaseBalance(address sender, uint256 amount) private {
        uint256 oldBalance = _balances[sender];
        uint256 newBalance = oldBalance - amount;
        require(oldBalance & FLAGGING_MASK == newBalance & FLAGGING_MASK, "underflow");
        _balances[sender] = newBalance;
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an `Approval` event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _allowances[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
     // solhint-disable-next-line no-empty-blocks
    function _beforeTokenTransfer(address from, address to, uint256 amount) virtual internal {
        // intentionally left blank
    }

}

File 3 of 12 : ERC20Named.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./ERC20Flaggable.sol";
import "../utils/Ownable.sol";

contract ERC20Named is ERC20Flaggable, Ownable {

    string public override name;
    string public override symbol;

    constructor(string memory _symbol, string memory _name, uint8 _decimals, address _admin) ERC20Flaggable(_decimals) Ownable(_admin) {
        setNameInternal(_symbol, _name);
    }

    function setName(string memory _symbol, string memory _name) external onlyOwner {
        setNameInternal(_symbol, _name);
    }

    function setNameInternal(string memory _symbol, string memory _name) internal {
        symbol = _symbol;
        name = _name;
        emit NameChanged(_name, _symbol);
    }

}

File 4 of 12 : ERC20PermitLight.sol
// SPDX-License-Identifier: MIT
// Copied from https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol
// and modified it.

pragma solidity ^0.8.0;

import "./ERC20Flaggable.sol";
import "./IERC20Permit.sol";

abstract contract ERC20PermitLight is ERC20Flaggable, IERC20Permit {
   
   /*//////////////////////////////////////////////////////////////
                            EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(address => uint256) public override nonces;

  /*//////////////////////////////////////////////////////////////
                             EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public override {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        unchecked { // unchecked to save a little gas with the nonce increment...
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"),
                                bytes32(0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
            _approve(recoveredAddress, spender, value);
        }
    }

    function DOMAIN_SEPARATOR() public view override returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    //keccak256("EIP712Domain(uint256 chainId,address verifyingContract)");
                    bytes32(0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218),
                    block.chainid,
                    address(this)
                )
            );
    }

}

File 5 of 12 : IERC20.sol
/**
* SPDX-License-Identifier: MIT
*
* Copyright (c) 2016-2019 zOS Global Limited
*
*/
pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see `ERC20Detailed`.
 */

interface IERC20 {

    // Optional functions
    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);

    /**
     * @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.
     *
     * > Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an `Approval` event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a `Transfer` event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to `approve`. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

}

File 6 of 12 : IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
// Copied from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/draft-IERC20Permit.sol

pragma solidity ^0.8.0;

import "./IERC20.sol";

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit is IERC20 {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 7 of 12 : IERC677Receiver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Given that development on ERC 677 has stalled, we should consider supporting EIP 1363: https://eips.ethereum.org/EIPS/eip-1363
interface IERC677Receiver {
    
    function onTokenTransfer(address from, uint256 amount, bytes calldata data) external returns (bool);

}

File 8 of 12 : ERC20Recoverable.sol
/**
* SPDX-License-Identifier: LicenseRef-Aktionariat
*
* MIT License with Automated License Fee Payments
*
* Copyright (c) 2020 Aktionariat AG (aktionariat.com)
*
* Permission is hereby granted to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* - The above copyright notice and this permission notice shall be included in
*   all copies or substantial portions of the Software.
* - All automated license fee payments integrated into this and related Software
*   are preserved.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
pragma solidity ^0.8.0;

import "../ERC20/ERC20Flaggable.sol";
import "./IRecoveryHub.sol";
import "./IRecoverable.sol";

/**
 * @title Recoverable
 * In case of tokens that represent real-world assets such as shares of a company, one needs a way
 * to handle lost private keys. With physical certificates, courts can declare share certificates as
 * invalid so the company can issue replacements. Here, we want a solution that does not depend on
 * third parties to resolve such cases. Instead, when someone has lost a private key, he can use the
 * declareLost function on the recovery hub to post a deposit and claim that the shares assigned to a
 * specific address are lost.
 * If an attacker trying to claim shares belonging to someone else, they risk losing the deposit
 * as it can be claimed at anytime by the rightful owner.
 * Furthermore, if "getClaimDeleter" is defined in the subclass, the returned address is allowed to
 * delete claims, returning the collateral. This can help to prevent obvious cases of abuse of the claim
 * function, e.g. cases of front-running.
 * Most functionality is implemented in a shared RecoveryHub.
 */
abstract contract ERC20Recoverable is ERC20Flaggable, IRecoverable {

    uint8 private constant FLAG_CLAIM_PRESENT = 10;

    // ERC-20 token that can be used as collateral or 0x0 if disabled
    IERC20 public customCollateralAddress;
    // Rate the custom collateral currency is multiplied to be valued like one share.
    uint256 public customCollateralRate;

    uint256 constant CLAIM_PERIOD = 180 days;

    IRecoveryHub public override immutable recovery;

    constructor(IRecoveryHub recoveryHub){
        recovery = recoveryHub;
    }

    /**
     * Returns the collateral rate for the given collateral type and 0 if that type
     * of collateral is not accepted. By default, only the token itself is accepted at
     * a rate of 1:1.
     *
     * Subclasses should override this method if they want to add additional types of
     * collateral.
     */
    function getCollateralRate(IERC20 collateralType) public override virtual view returns (uint256) {
        if (address(collateralType) == address(this)) {
            return 1;
        } else if (collateralType == customCollateralAddress) {
            return customCollateralRate;
        } else {
            return 0;
        }
    }

    function claimPeriod() external pure override returns (uint256){
        return CLAIM_PERIOD;
    }

    /**
     * Allows subclasses to set a custom collateral besides the token itself.
     * The collateral must be an ERC-20 token that returns true on successful transfers and
     * throws an exception or returns false on failure.
     * Also, do not forget to multiply the rate in accordance with the number of decimals of the collateral.
     * For example, rate should be 7*10**18 for 7 units of a collateral with 18 decimals.
     */
    function _setCustomClaimCollateral(IERC20 collateral, uint256 rate) internal {
        customCollateralAddress = collateral;
        if (address(customCollateralAddress) == address(0)) {
            customCollateralRate = 0; // disabled
        } else {
            require(rate > 0, "zero");
            customCollateralRate = rate;
        }
    }

    function getClaimDeleter() virtual public view returns (address);

    function transfer(address recipient, uint256 amount) override(ERC20Flaggable, IERC20) virtual public returns (bool) {
        require(super.transfer(recipient, amount), "transfer");
        if (hasFlagInternal(msg.sender, FLAG_CLAIM_PRESENT)){
            recovery.clearClaimFromToken(msg.sender);
        }
        return true;
    }

    function notifyClaimMade(address target) external override {
        require(msg.sender == address(recovery), "not recovery");
        setFlag(target, FLAG_CLAIM_PRESENT, true);
    }

    function notifyClaimDeleted(address target) external override {
        require(msg.sender == address(recovery), "not recovery");
        setFlag(target, FLAG_CLAIM_PRESENT, false);
    }

    function deleteClaim(address lostAddress) external {
        require(msg.sender == getClaimDeleter(), "not claim deleter");
        recovery.deleteClaim(lostAddress);
    }

    function recover(address oldAddress, address newAddress) external override {
        require(msg.sender == address(recovery), "not recovery");
        _transfer(oldAddress, newAddress, balanceOf(oldAddress));
    }

}

File 9 of 12 : IRecoverable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "../ERC20/IERC20.sol";
import "./IRecoveryHub.sol";

interface IRecoverable is IERC20{

    // returns the recovery hub
    function recovery() external view returns (IRecoveryHub);

    function claimPeriod() external view returns (uint256);
    
    function notifyClaimMade(address target) external;

    function notifyClaimDeleted(address target) external;

    function getCollateralRate(IERC20 collateral) external view returns(uint256);

    function recover(address oldAddress, address newAddress) external;

}

File 10 of 12 : IRecoveryHub.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./IRecoverable.sol";

interface IRecoveryHub {

    function setRecoverable(bool flag) external;
    
    // deletes claim and transfers collateral back to claimer
    function deleteClaim(address target) external;

    // clears claim and transfers collateral to holder
    function clearClaimFromToken(address holder) external;

    function clearClaimFromUser(IRecoverable token) external;

}

File 11 of 12 : IShares.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IShares {
	function burn(uint256) external;

	function totalShares() external view returns (uint256);
}

File 12 of 12 : Ownable.sol
// SPDX-License-Identifier: MIT
//
// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol
//
// Modifications:
// - Replaced Context._msgSender() with msg.sender
// - Made leaner
// - Extracted interface

pragma solidity ^0.8.0;

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
contract Ownable {

    address public owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor (address initialOwner) {
        owner = initialOwner;
        emit OwnershipTransferred(address(0), owner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) external onlyOwner {
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }

    modifier onlyOwner() {
        require(owner == msg.sender, "not owner");
        _;
    }
}

Settings
{
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_terms","type":"string"},{"internalType":"uint256","name":"_totalShares","type":"uint256"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"contract IRecoveryHub","name":"_recoveryHub","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"message","type":"string"}],"name":"Announcement","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"terms","type":"string"}],"name":"ChangeTerms","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"total","type":"uint256"}],"name":"ChangeTotalShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"symbol","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"string","name":"message","type":"string"}],"name":"TokensDeclaredInvalid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"message","type":"string"}],"name":"announcement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"customCollateralAddress","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"customCollateralRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"message","type":"string"}],"name":"declareInvalid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lostAddress","type":"address"}],"name":"deleteClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getClaimDeleter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"collateralType","type":"address"}],"name":"getCollateralRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint8","name":"number","type":"uint8"}],"name":"hasFlag","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"invalidTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"shareholder","type":"address"},{"internalType":"address","name":"callee","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mintAndCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"target","type":"address[]"},{"internalType":"uint256[]","name":"amount","type":"uint256[]"}],"name":"mintMany","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"target","type":"address[]"},{"internalType":"address","name":"callee","type":"address"},{"internalType":"uint256[]","name":"amount","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mintManyAndCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"notifyClaimDeleted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"notifyClaimMade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"oldAddress","type":"address"},{"internalType":"address","name":"newAddress","type":"address"}],"name":"recover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recovery","outputs":[{"internalType":"contract IRecoveryHub","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"rate","type":"uint256"}],"name":"setCustomClaimCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_name","type":"string"}],"name":"setName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_terms","type":"string"}],"name":"setTerms","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newTotalShares","type":"uint256"}],"name":"setTotalShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"terms","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalValidSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"transferAndCall","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a06040523480156200001157600080fd5b506040516200255138038062002551833981016040819052620000349162000338565b6003805460ff191690556001600160a01b03818116608052600580546001600160a01b031916918416918217905560405187918791600091869182919084907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350620000a5848462000134565b505050600a849055508351620000c39060099060208701906200019f565b506000600b819055604051636427ed9760e01b815260048101919091526001600160a01b03821690636427ed9790602401600060405180830381600087803b1580156200010f57600080fd5b505af115801562000124573d6000803e3d6000fd5b505050505050505050506200049b565b8151620001499060079060208501906200019f565b5080516200015f9060069060208401906200019f565b507f6c20b91d1723b78732eba64ff11ebd7966a6e4af568a00fa4f6b72c20f58b02a8183604051620001939291906200042c565b60405180910390a15050565b828054620001ad906200045e565b90600052602060002090601f016020900481019282620001d157600085556200021c565b82601f10620001ec57805160ff19168380011785556200021c565b828001600101855582156200021c579182015b828111156200021c578251825591602001919060010190620001ff565b506200022a9291506200022e565b5090565b5b808211156200022a57600081556001016200022f565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620002785781810151838201526020016200025e565b8381111562000288576000848401525b50505050565b600082601f830112620002a057600080fd5b81516001600160401b0380821115620002bd57620002bd62000245565b604051601f8301601f19908116603f01168101908282118183101715620002e857620002e862000245565b816040528381528660208588010111156200030257600080fd5b620003158460208301602089016200025b565b9695505050505050565b6001600160a01b03811681146200033557600080fd5b50565b60008060008060008060c087890312156200035257600080fd5b86516001600160401b03808211156200036a57600080fd5b620003788a838b016200028e565b975060208901519150808211156200038f57600080fd5b6200039d8a838b016200028e565b96506040890151915080821115620003b457600080fd5b50620003c389828a016200028e565b945050606087015192506080870151620003dd816200031f565b60a0880151909250620003f0816200031f565b809150509295509295509295565b60008151808452620004188160208601602086016200025b565b601f01601f19169290920160200192915050565b604081526000620004416040830185620003fe565b8281036020840152620004558185620003fe565b95945050505050565b600181811c908216806200047357607f821691505b602082108114156200049557634e487b7160e01b600052602260045260246000fd5b50919050565b608051612077620004da60003960008181610536015281816107a401528181610c7301528181610e97015281816110e901526114fe01526120776000f3fe608060405234801561001057600080fd5b506004361061025e5760003560e01c8063648bf77411610146578063b0d04c7a116100c3578063ddceafa911610087578063ddceafa914610531578063e5b824ec14610558578063f2fde38b1461056b578063f54fc0601461057e578063f5c0b95f14610591578063ffa1ad74146105a457600080fd5b8063b0d04c7a146104c2578063c18172c4146104ca578063d5025625146104dd578063d505accf146104e5578063dd62ed3e146104f857600080fd5b80637ecebe001161010a5780637ecebe00146104615780638da5cb5b1461048157806395d89b4114610494578063a77384c11461049c578063a9059cbb146104af57600080fd5b8063648bf7741461040c57806370a082311461041f57806377e071ad1461043257806378f86afc146104455780637dc2cd981461045857600080fd5b806337a8129c116101df57806340c10f19116101a357806340c10f19146103a457806342966c68146103b7578063487346b2146103ca5780635c707f07146103dd5780635d6624b7146103f0578063609181171461040357600080fd5b806337a8129c146103595780633a1cdf32146103625780633a98ef39146103755780634000aea01461037e5780634029a3ce1461039157600080fd5b806323b872dd1161022657806323b872dd146102fb5780632a0a4ed51461030e578063313ce5671461031f57806332a7ae951461033e5780633644e5151461035157600080fd5b806306fdde0314610263578063095ea7b3146102815780630c6f0e5d146102a457806318160ddd146102d45780631f0f06aa146102e6575b600080fd5b61026b6105ac565b60405161027891906118a8565b60405180910390f35b61029461028f3660046118d0565b61063a565b6040519015158152602001610278565b6003546102bc9061010090046001600160a01b031681565b6040516001600160a01b039091168152602001610278565b6002545b604051908152602001610278565b6102f96102f4366004611945565b610650565b005b610294610309366004611987565b6106c0565b6005546001600160a01b03166102bc565b60035461032c9060ff1681565b60405160ff9091168152602001610278565b6102f961034c3660046119c8565b610737565b6102d8610803565b6102d8600b5481565b6102f96103703660046118d0565b61085c565b6102d8600a5481565b61029461038c3660046119e5565b610894565b6102f961039f366004611a86565b610925565b6102f96103b23660046118d0565b6109c9565b6102f96103c5366004611ae6565b6109fd565b6102f96103d8366004611aff565b610a15565b6102f96103eb366004611c51565b610b56565b6102f96103fe3660046119e5565b610b8a565b6102d860045481565b6102f961041a366004611cb5565b610c68565b6102d861042d3660046119c8565b610cc3565b6102d86104403660046119c8565b610ce7565b6102f9610453366004611cee565b610d32565b62ed4e006102d8565b6102d861046f3660046119c8565b60086020526000908152604090205481565b6005546102bc906001600160a01b031681565b61026b610daa565b6102f96104aa366004611ae6565b610db7565b6102946104bd3660046118d0565b610e5c565b6102d8610e6f565b6102f96104d83660046119c8565b610e8c565b61026b610ee1565b6102f96104f3366004611d3c565b610eee565b6102d8610506366004611cb5565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6102bc7f000000000000000000000000000000000000000000000000000000000000000081565b6102f96105663660046119c8565b6110de565b6102f96105793660046119c8565b611133565b6102f961058c366004611daa565b6111b9565b61029461059f366004611e1d565b611241565b61032c600381565b600680546105b990611e52565b80601f01602080910402602001604051908101604052809291908181526020018280546105e590611e52565b80156106325780601f1061060757610100808354040283529160200191610632565b820191906000526020600020905b81548152906001019060200180831161061557829003601f168201915b505050505081565b600061064733848461124d565b50600192915050565b6005546001600160a01b031633146106835760405162461bcd60e51b815260040161067a90611e8d565b60405180910390fd5b7f07ce702fc13ca0620c174dab22996a6d5fd9e7accb663555a4e85323692706ba82826040516106b4929190611ed9565b60405180910390a15050565b60006106cd8484846112af565b6001600160a01b0384166000908152600160209081526040808320338452909152902054600160ff1b81101561072c576107078382611f03565b6001600160a01b03861660009081526001602090815260408083203384529091529020555b506001949350505050565b6005546001600160a01b031633146107855760405162461bcd60e51b81526020600482015260116024820152703737ba1031b630b4b6903232b632ba32b960791b604482015260640161067a565b6040516332a7ae9560e01b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906332a7ae9590602401600060405180830381600087803b1580156107e857600080fd5b505af11580156107fc573d6000803e3d6000fd5b5050505050565b604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692186020820152469181019190915230606082015260009060800160405160208183030381529060405280519060200120905090565b6005546001600160a01b031633146108865760405162461bcd60e51b815260040161067a90611e8d565b6108908282611308565b5050565b60006108a08585610e5c565b801561091c5750604051635260769b60e11b81526001600160a01b0386169063a4c0ed36906108d9903390889088908890600401611f1a565b6020604051808303816000875af11580156108f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091c9190611f4c565b95945050505050565b6005546001600160a01b0316331461094f5760405162461bcd60e51b815260040161067a90611e8d565b8281811461095c57600080fd5b60005b818110156109c1576109af86868381811061097c5761097c611f6e565b905060200201602081019061099191906119c8565b8585848181106109a3576109a3611f6e565b9050602002013561137f565b806109b981611f84565b91505061095f565b505050505050565b6005546001600160a01b031633146109f35760405162461bcd60e51b815260040161067a90611e8d565b610890828261137f565b610a083330836112af565b610a1230826113d5565b50565b85838114610a2257600080fd5b6000805b82811015610a6657868682818110610a4057610a40611f6e565b9050602002013582610a529190611f9f565b915080610a5e81611f84565b915050610a26565b50610a7187826109c9565b60005b82811015610b4a57876001600160a01b031663a4c0ed368b8b84818110610a9d57610a9d611f6e565b9050602002016020810190610ab291906119c8565b898985818110610ac457610ac4611f6e565b9050602002013588886040518563ffffffff1660e01b8152600401610aec9493929190611f1a565b6020604051808303816000875af1158015610b0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2f9190611f4c565b610b3857600080fd5b80610b4281611f84565b915050610a74565b50505050505050505050565b6005546001600160a01b03163314610b805760405162461bcd60e51b815260040161067a90611e8d565b610890828261143d565b6005546001600160a01b03163314610bb45760405162461bcd60e51b815260040161067a90611e8d565b6000610bbf85610cc3565b905080841115610c035760405162461bcd60e51b815260206004820152600f60248201526e0c2dadeeadce840e8dede40d0d2ced608b1b604482015260640161067a565b83600b6000828254610c159190611f9f565b92505081905550846001600160a01b03167f0a605cd1294f60fa3b73548ac68428f33300a051f225afcdcc75e56083c96ee7858585604051610c5993929190611fb7565b60405180910390a25050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cb05760405162461bcd60e51b815260040161067a90611fd1565b6108908282610cbe85610cc3565b6112af565b6001600160a01b03166000908152602081905260409020546001600160e01b031690565b60006001600160a01b038216301415610d0257506001919050565b6003546001600160a01b03838116610100909204161415610d2557505060045490565b506000919050565b919050565b6005546001600160a01b03163314610d5c5760405162461bcd60e51b815260040161067a90611e8d565b8051610d6f9060099060208401906117c2565b507fe9f2468ecc8d3dff15a70a5909151e6297cee4cf05268eff3d7ef0c696ec50f281604051610d9f91906118a8565b60405180910390a150565b600780546105b990611e52565b6005546001600160a01b03163314610de15760405162461bcd60e51b815260040161067a90611e8d565b610de9610e6f565b811015610e275760405162461bcd60e51b815260206004820152600c60248201526b62656c6f7720737570706c7960a01b604482015260640161067a565b600a8190556040518181527fdcbf73bf1e396dbe03ccbcd29c0aa52eb8028ae24726098296357286de4f5b2690602001610d9f565b6000610e688383611496565b9392505050565b6000600b54610e7d60025490565b610e879190611f03565b905090565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610ed45760405162461bcd60e51b815260040161067a90611fd1565b610a1281600a600161156b565b600980546105b990611e52565b42841015610f3e5760405162461bcd60e51b815260206004820152601760248201527f5045524d49545f444541444c494e455f45585049524544000000000000000000604482015260640161067a565b60006001610f4a610803565b6001600160a01b038a811660008181526008602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e08301909152805192019190912061190160f01b6101008301526101028201929092526101228101919091526101420160408051601f198184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015611056573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580159061108c5750876001600160a01b0316816001600160a01b0316145b6110c95760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa9a4a3a722a960911b604482015260640161067a565b6110d481888861124d565b5050505050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146111265760405162461bcd60e51b815260040161067a90611fd1565b610a1281600a600061156b565b6005546001600160a01b0316331461115d5760405162461bcd60e51b815260040161067a90611e8d565b6005546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600580546001600160a01b0319166001600160a01b0392909216919091179055565b6111c384846109c9565b604051635260769b60e11b81526001600160a01b0385169063a4c0ed36906111f5908890879087908790600401611f1a565b6020604051808303816000875af1158015611214573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112389190611f4c565b6107fc57600080fd5b6000610e6883836115cf565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6112b9838261160f565b6112c382826116a5565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516112a291815260200190565b60038054610100600160a81b0319166101006001600160a01b0385811682029290921792839055909104166113405760006004555050565b600081116113795760405162461bcd60e51b815260040161067a906020808252600490820152637a65726f60e01b604082015260600190565b60045550565b600a548161138b610e6f565b6113959190611f9f565b11156113cb5760405162461bcd60e51b81526020600482015260056024820152641d1bdd185b60da1b604482015260640161067a565b6108908282611755565b80600260008282546113e79190611f03565b909155506113f79050828261160f565b6040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b81516114509060079060208501906117c2565b5080516114649060069060208401906117c2565b507f6c20b91d1723b78732eba64ff11ebd7966a6e4af568a00fa4f6b72c20f58b02a81836040516106b4929190611ff7565b60006114a283836117b5565b6114d95760405162461bcd60e51b81526020600482015260086024820152673a3930b739b332b960c11b604482015260640161067a565b6114e433600a6115cf565b15610647576040516304d301a360e41b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690634d301a3090602401600060405180830381600087803b15801561154a57600080fd5b505af115801561155e573d6000803e3d6000fd5b5050505050600192915050565b60006115788360e061201c565b6001600160a01b038516600090815260208190526040902054600160ff929092169190911b91508082168214831515146107fc576001600160a01b0394909416600090815260208190526040902093189092555050565b6000806115dd8360e061201c565b6001600160a01b038516600090815260208190526040902054600160ff929092169190911b9081161491505092915050565b6001600160a01b038216600090815260208190526040812054906116338383611f03565b90506001600160e01b031981166001600160e01b03198316146116845760405162461bcd60e51b8152602060048201526009602482015268756e646572666c6f7760b81b604482015260640161067a565b6001600160a01b039093166000908152602081905260409020929092555050565b6001600160a01b0382166116e15760405162461bcd60e51b815260206004820152600360248201526203078360ec1b604482015260640161067a565b6001600160a01b038216600090815260208190526040812054906117058383611f9f565b90506001600160e01b031981166001600160e01b03198316146116845760405162461bcd60e51b81526020600482015260086024820152676f766572666c6f7760c01b604482015260640161067a565b80600260008282546117679190611f9f565b90915550611777905082826116a5565b6040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001611431565b60006106473384846112af565b8280546117ce90611e52565b90600052602060002090601f0160209004810192826117f05760008555611836565b82601f1061180957805160ff1916838001178555611836565b82800160010185558215611836579182015b8281111561183657825182559160200191906001019061181b565b50611842929150611846565b5090565b5b808211156118425760008155600101611847565b6000815180845260005b8181101561188157602081850181015186830182015201611865565b81811115611893576000602083870101525b50601f01601f19169290920160200192915050565b602081526000610e68602083018461185b565b6001600160a01b0381168114610a1257600080fd5b600080604083850312156118e357600080fd5b82356118ee816118bb565b946020939093013593505050565b60008083601f84011261190e57600080fd5b50813567ffffffffffffffff81111561192657600080fd5b60208301915083602082850101111561193e57600080fd5b9250929050565b6000806020838503121561195857600080fd5b823567ffffffffffffffff81111561196f57600080fd5b61197b858286016118fc565b90969095509350505050565b60008060006060848603121561199c57600080fd5b83356119a7816118bb565b925060208401356119b7816118bb565b929592945050506040919091013590565b6000602082840312156119da57600080fd5b8135610e68816118bb565b600080600080606085870312156119fb57600080fd5b8435611a06816118bb565b935060208501359250604085013567ffffffffffffffff811115611a2957600080fd5b611a35878288016118fc565b95989497509550505050565b60008083601f840112611a5357600080fd5b50813567ffffffffffffffff811115611a6b57600080fd5b6020830191508360208260051b850101111561193e57600080fd5b60008060008060408587031215611a9c57600080fd5b843567ffffffffffffffff80821115611ab457600080fd5b611ac088838901611a41565b90965094506020870135915080821115611ad957600080fd5b50611a3587828801611a41565b600060208284031215611af857600080fd5b5035919050565b60008060008060008060006080888a031215611b1a57600080fd5b873567ffffffffffffffff80821115611b3257600080fd5b611b3e8b838c01611a41565b909950975060208a01359150611b53826118bb565b90955060408901359080821115611b6957600080fd5b611b758b838c01611a41565b909650945060608a0135915080821115611b8e57600080fd5b50611b9b8a828b016118fc565b989b979a50959850939692959293505050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112611bd557600080fd5b813567ffffffffffffffff80821115611bf057611bf0611bae565b604051601f8301601f19908116603f01168101908282118183101715611c1857611c18611bae565b81604052838152866020858801011115611c3157600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215611c6457600080fd5b823567ffffffffffffffff80821115611c7c57600080fd5b611c8886838701611bc4565b93506020850135915080821115611c9e57600080fd5b50611cab85828601611bc4565b9150509250929050565b60008060408385031215611cc857600080fd5b8235611cd3816118bb565b91506020830135611ce3816118bb565b809150509250929050565b600060208284031215611d0057600080fd5b813567ffffffffffffffff811115611d1757600080fd5b611d2384828501611bc4565b949350505050565b803560ff81168114610d2d57600080fd5b600080600080600080600060e0888a031215611d5757600080fd5b8735611d62816118bb565b96506020880135611d72816118bb565b95506040880135945060608801359350611d8e60808901611d2b565b925060a0880135915060c0880135905092959891949750929550565b600080600080600060808688031215611dc257600080fd5b8535611dcd816118bb565b94506020860135611ddd816118bb565b935060408601359250606086013567ffffffffffffffff811115611e0057600080fd5b611e0c888289016118fc565b969995985093965092949392505050565b60008060408385031215611e3057600080fd5b8235611e3b816118bb565b9150611e4960208401611d2b565b90509250929050565b600181811c90821680611e6657607f821691505b60208210811415611e8757634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600990820152683737ba1037bbb732b960b91b604082015260600190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000611d23602083018486611eb0565b634e487b7160e01b600052601160045260246000fd5b600082821015611f1557611f15611eed565b500390565b60018060a01b0385168152836020820152606060408201526000611f42606083018486611eb0565b9695505050505050565b600060208284031215611f5e57600080fd5b81518015158114610e6857600080fd5b634e487b7160e01b600052603260045260246000fd5b6000600019821415611f9857611f98611eed565b5060010190565b60008219821115611fb257611fb2611eed565b500190565b83815260406020820152600061091c604083018486611eb0565b6020808252600c908201526b6e6f74207265636f7665727960a01b604082015260600190565b60408152600061200a604083018561185b565b828103602084015261091c818561185b565b600060ff821660ff84168060ff0382111561203957612039611eed565b01939250505056fea2646970667358221220af38428c7eb44f06c049ef2230f226f33b89d817622fc80fa19aabd7ed9c780d64736f6c634300080c003300000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000019316000000000000000000000000042ad6513979694794947475f82eb5e3d74d0c4cd000000000000000000000000f00b91839ff7a6ac6dddac7e73d2f222c19a9ec3000000000000000000000000000000000000000000000000000000000000000353504f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002453706f727473706172616469736520537769747a65726c616e642041472053686172657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003168747470733a2f2f7777772e73706f72747370617261646973652e63682f706167652f63726f7764696e76657374696e67000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061025e5760003560e01c8063648bf77411610146578063b0d04c7a116100c3578063ddceafa911610087578063ddceafa914610531578063e5b824ec14610558578063f2fde38b1461056b578063f54fc0601461057e578063f5c0b95f14610591578063ffa1ad74146105a457600080fd5b8063b0d04c7a146104c2578063c18172c4146104ca578063d5025625146104dd578063d505accf146104e5578063dd62ed3e146104f857600080fd5b80637ecebe001161010a5780637ecebe00146104615780638da5cb5b1461048157806395d89b4114610494578063a77384c11461049c578063a9059cbb146104af57600080fd5b8063648bf7741461040c57806370a082311461041f57806377e071ad1461043257806378f86afc146104455780637dc2cd981461045857600080fd5b806337a8129c116101df57806340c10f19116101a357806340c10f19146103a457806342966c68146103b7578063487346b2146103ca5780635c707f07146103dd5780635d6624b7146103f0578063609181171461040357600080fd5b806337a8129c146103595780633a1cdf32146103625780633a98ef39146103755780634000aea01461037e5780634029a3ce1461039157600080fd5b806323b872dd1161022657806323b872dd146102fb5780632a0a4ed51461030e578063313ce5671461031f57806332a7ae951461033e5780633644e5151461035157600080fd5b806306fdde0314610263578063095ea7b3146102815780630c6f0e5d146102a457806318160ddd146102d45780631f0f06aa146102e6575b600080fd5b61026b6105ac565b60405161027891906118a8565b60405180910390f35b61029461028f3660046118d0565b61063a565b6040519015158152602001610278565b6003546102bc9061010090046001600160a01b031681565b6040516001600160a01b039091168152602001610278565b6002545b604051908152602001610278565b6102f96102f4366004611945565b610650565b005b610294610309366004611987565b6106c0565b6005546001600160a01b03166102bc565b60035461032c9060ff1681565b60405160ff9091168152602001610278565b6102f961034c3660046119c8565b610737565b6102d8610803565b6102d8600b5481565b6102f96103703660046118d0565b61085c565b6102d8600a5481565b61029461038c3660046119e5565b610894565b6102f961039f366004611a86565b610925565b6102f96103b23660046118d0565b6109c9565b6102f96103c5366004611ae6565b6109fd565b6102f96103d8366004611aff565b610a15565b6102f96103eb366004611c51565b610b56565b6102f96103fe3660046119e5565b610b8a565b6102d860045481565b6102f961041a366004611cb5565b610c68565b6102d861042d3660046119c8565b610cc3565b6102d86104403660046119c8565b610ce7565b6102f9610453366004611cee565b610d32565b62ed4e006102d8565b6102d861046f3660046119c8565b60086020526000908152604090205481565b6005546102bc906001600160a01b031681565b61026b610daa565b6102f96104aa366004611ae6565b610db7565b6102946104bd3660046118d0565b610e5c565b6102d8610e6f565b6102f96104d83660046119c8565b610e8c565b61026b610ee1565b6102f96104f3366004611d3c565b610eee565b6102d8610506366004611cb5565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6102bc7f000000000000000000000000f00b91839ff7a6ac6dddac7e73d2f222c19a9ec381565b6102f96105663660046119c8565b6110de565b6102f96105793660046119c8565b611133565b6102f961058c366004611daa565b6111b9565b61029461059f366004611e1d565b611241565b61032c600381565b600680546105b990611e52565b80601f01602080910402602001604051908101604052809291908181526020018280546105e590611e52565b80156106325780601f1061060757610100808354040283529160200191610632565b820191906000526020600020905b81548152906001019060200180831161061557829003601f168201915b505050505081565b600061064733848461124d565b50600192915050565b6005546001600160a01b031633146106835760405162461bcd60e51b815260040161067a90611e8d565b60405180910390fd5b7f07ce702fc13ca0620c174dab22996a6d5fd9e7accb663555a4e85323692706ba82826040516106b4929190611ed9565b60405180910390a15050565b60006106cd8484846112af565b6001600160a01b0384166000908152600160209081526040808320338452909152902054600160ff1b81101561072c576107078382611f03565b6001600160a01b03861660009081526001602090815260408083203384529091529020555b506001949350505050565b6005546001600160a01b031633146107855760405162461bcd60e51b81526020600482015260116024820152703737ba1031b630b4b6903232b632ba32b960791b604482015260640161067a565b6040516332a7ae9560e01b81526001600160a01b0382811660048301527f000000000000000000000000f00b91839ff7a6ac6dddac7e73d2f222c19a9ec316906332a7ae9590602401600060405180830381600087803b1580156107e857600080fd5b505af11580156107fc573d6000803e3d6000fd5b5050505050565b604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692186020820152469181019190915230606082015260009060800160405160208183030381529060405280519060200120905090565b6005546001600160a01b031633146108865760405162461bcd60e51b815260040161067a90611e8d565b6108908282611308565b5050565b60006108a08585610e5c565b801561091c5750604051635260769b60e11b81526001600160a01b0386169063a4c0ed36906108d9903390889088908890600401611f1a565b6020604051808303816000875af11580156108f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091c9190611f4c565b95945050505050565b6005546001600160a01b0316331461094f5760405162461bcd60e51b815260040161067a90611e8d565b8281811461095c57600080fd5b60005b818110156109c1576109af86868381811061097c5761097c611f6e565b905060200201602081019061099191906119c8565b8585848181106109a3576109a3611f6e565b9050602002013561137f565b806109b981611f84565b91505061095f565b505050505050565b6005546001600160a01b031633146109f35760405162461bcd60e51b815260040161067a90611e8d565b610890828261137f565b610a083330836112af565b610a1230826113d5565b50565b85838114610a2257600080fd5b6000805b82811015610a6657868682818110610a4057610a40611f6e565b9050602002013582610a529190611f9f565b915080610a5e81611f84565b915050610a26565b50610a7187826109c9565b60005b82811015610b4a57876001600160a01b031663a4c0ed368b8b84818110610a9d57610a9d611f6e565b9050602002016020810190610ab291906119c8565b898985818110610ac457610ac4611f6e565b9050602002013588886040518563ffffffff1660e01b8152600401610aec9493929190611f1a565b6020604051808303816000875af1158015610b0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2f9190611f4c565b610b3857600080fd5b80610b4281611f84565b915050610a74565b50505050505050505050565b6005546001600160a01b03163314610b805760405162461bcd60e51b815260040161067a90611e8d565b610890828261143d565b6005546001600160a01b03163314610bb45760405162461bcd60e51b815260040161067a90611e8d565b6000610bbf85610cc3565b905080841115610c035760405162461bcd60e51b815260206004820152600f60248201526e0c2dadeeadce840e8dede40d0d2ced608b1b604482015260640161067a565b83600b6000828254610c159190611f9f565b92505081905550846001600160a01b03167f0a605cd1294f60fa3b73548ac68428f33300a051f225afcdcc75e56083c96ee7858585604051610c5993929190611fb7565b60405180910390a25050505050565b336001600160a01b037f000000000000000000000000f00b91839ff7a6ac6dddac7e73d2f222c19a9ec31614610cb05760405162461bcd60e51b815260040161067a90611fd1565b6108908282610cbe85610cc3565b6112af565b6001600160a01b03166000908152602081905260409020546001600160e01b031690565b60006001600160a01b038216301415610d0257506001919050565b6003546001600160a01b03838116610100909204161415610d2557505060045490565b506000919050565b919050565b6005546001600160a01b03163314610d5c5760405162461bcd60e51b815260040161067a90611e8d565b8051610d6f9060099060208401906117c2565b507fe9f2468ecc8d3dff15a70a5909151e6297cee4cf05268eff3d7ef0c696ec50f281604051610d9f91906118a8565b60405180910390a150565b600780546105b990611e52565b6005546001600160a01b03163314610de15760405162461bcd60e51b815260040161067a90611e8d565b610de9610e6f565b811015610e275760405162461bcd60e51b815260206004820152600c60248201526b62656c6f7720737570706c7960a01b604482015260640161067a565b600a8190556040518181527fdcbf73bf1e396dbe03ccbcd29c0aa52eb8028ae24726098296357286de4f5b2690602001610d9f565b6000610e688383611496565b9392505050565b6000600b54610e7d60025490565b610e879190611f03565b905090565b336001600160a01b037f000000000000000000000000f00b91839ff7a6ac6dddac7e73d2f222c19a9ec31614610ed45760405162461bcd60e51b815260040161067a90611fd1565b610a1281600a600161156b565b600980546105b990611e52565b42841015610f3e5760405162461bcd60e51b815260206004820152601760248201527f5045524d49545f444541444c494e455f45585049524544000000000000000000604482015260640161067a565b60006001610f4a610803565b6001600160a01b038a811660008181526008602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e08301909152805192019190912061190160f01b6101008301526101028201929092526101228101919091526101420160408051601f198184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015611056573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580159061108c5750876001600160a01b0316816001600160a01b0316145b6110c95760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa9a4a3a722a960911b604482015260640161067a565b6110d481888861124d565b5050505050505050565b336001600160a01b037f000000000000000000000000f00b91839ff7a6ac6dddac7e73d2f222c19a9ec316146111265760405162461bcd60e51b815260040161067a90611fd1565b610a1281600a600061156b565b6005546001600160a01b0316331461115d5760405162461bcd60e51b815260040161067a90611e8d565b6005546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600580546001600160a01b0319166001600160a01b0392909216919091179055565b6111c384846109c9565b604051635260769b60e11b81526001600160a01b0385169063a4c0ed36906111f5908890879087908790600401611f1a565b6020604051808303816000875af1158015611214573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112389190611f4c565b6107fc57600080fd5b6000610e6883836115cf565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6112b9838261160f565b6112c382826116a5565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516112a291815260200190565b60038054610100600160a81b0319166101006001600160a01b0385811682029290921792839055909104166113405760006004555050565b600081116113795760405162461bcd60e51b815260040161067a906020808252600490820152637a65726f60e01b604082015260600190565b60045550565b600a548161138b610e6f565b6113959190611f9f565b11156113cb5760405162461bcd60e51b81526020600482015260056024820152641d1bdd185b60da1b604482015260640161067a565b6108908282611755565b80600260008282546113e79190611f03565b909155506113f79050828261160f565b6040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b81516114509060079060208501906117c2565b5080516114649060069060208401906117c2565b507f6c20b91d1723b78732eba64ff11ebd7966a6e4af568a00fa4f6b72c20f58b02a81836040516106b4929190611ff7565b60006114a283836117b5565b6114d95760405162461bcd60e51b81526020600482015260086024820152673a3930b739b332b960c11b604482015260640161067a565b6114e433600a6115cf565b15610647576040516304d301a360e41b81523360048201527f000000000000000000000000f00b91839ff7a6ac6dddac7e73d2f222c19a9ec36001600160a01b031690634d301a3090602401600060405180830381600087803b15801561154a57600080fd5b505af115801561155e573d6000803e3d6000fd5b5050505050600192915050565b60006115788360e061201c565b6001600160a01b038516600090815260208190526040902054600160ff929092169190911b91508082168214831515146107fc576001600160a01b0394909416600090815260208190526040902093189092555050565b6000806115dd8360e061201c565b6001600160a01b038516600090815260208190526040902054600160ff929092169190911b9081161491505092915050565b6001600160a01b038216600090815260208190526040812054906116338383611f03565b90506001600160e01b031981166001600160e01b03198316146116845760405162461bcd60e51b8152602060048201526009602482015268756e646572666c6f7760b81b604482015260640161067a565b6001600160a01b039093166000908152602081905260409020929092555050565b6001600160a01b0382166116e15760405162461bcd60e51b815260206004820152600360248201526203078360ec1b604482015260640161067a565b6001600160a01b038216600090815260208190526040812054906117058383611f9f565b90506001600160e01b031981166001600160e01b03198316146116845760405162461bcd60e51b81526020600482015260086024820152676f766572666c6f7760c01b604482015260640161067a565b80600260008282546117679190611f9f565b90915550611777905082826116a5565b6040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001611431565b60006106473384846112af565b8280546117ce90611e52565b90600052602060002090601f0160209004810192826117f05760008555611836565b82601f1061180957805160ff1916838001178555611836565b82800160010185558215611836579182015b8281111561183657825182559160200191906001019061181b565b50611842929150611846565b5090565b5b808211156118425760008155600101611847565b6000815180845260005b8181101561188157602081850181015186830182015201611865565b81811115611893576000602083870101525b50601f01601f19169290920160200192915050565b602081526000610e68602083018461185b565b6001600160a01b0381168114610a1257600080fd5b600080604083850312156118e357600080fd5b82356118ee816118bb565b946020939093013593505050565b60008083601f84011261190e57600080fd5b50813567ffffffffffffffff81111561192657600080fd5b60208301915083602082850101111561193e57600080fd5b9250929050565b6000806020838503121561195857600080fd5b823567ffffffffffffffff81111561196f57600080fd5b61197b858286016118fc565b90969095509350505050565b60008060006060848603121561199c57600080fd5b83356119a7816118bb565b925060208401356119b7816118bb565b929592945050506040919091013590565b6000602082840312156119da57600080fd5b8135610e68816118bb565b600080600080606085870312156119fb57600080fd5b8435611a06816118bb565b935060208501359250604085013567ffffffffffffffff811115611a2957600080fd5b611a35878288016118fc565b95989497509550505050565b60008083601f840112611a5357600080fd5b50813567ffffffffffffffff811115611a6b57600080fd5b6020830191508360208260051b850101111561193e57600080fd5b60008060008060408587031215611a9c57600080fd5b843567ffffffffffffffff80821115611ab457600080fd5b611ac088838901611a41565b90965094506020870135915080821115611ad957600080fd5b50611a3587828801611a41565b600060208284031215611af857600080fd5b5035919050565b60008060008060008060006080888a031215611b1a57600080fd5b873567ffffffffffffffff80821115611b3257600080fd5b611b3e8b838c01611a41565b909950975060208a01359150611b53826118bb565b90955060408901359080821115611b6957600080fd5b611b758b838c01611a41565b909650945060608a0135915080821115611b8e57600080fd5b50611b9b8a828b016118fc565b989b979a50959850939692959293505050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112611bd557600080fd5b813567ffffffffffffffff80821115611bf057611bf0611bae565b604051601f8301601f19908116603f01168101908282118183101715611c1857611c18611bae565b81604052838152866020858801011115611c3157600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215611c6457600080fd5b823567ffffffffffffffff80821115611c7c57600080fd5b611c8886838701611bc4565b93506020850135915080821115611c9e57600080fd5b50611cab85828601611bc4565b9150509250929050565b60008060408385031215611cc857600080fd5b8235611cd3816118bb565b91506020830135611ce3816118bb565b809150509250929050565b600060208284031215611d0057600080fd5b813567ffffffffffffffff811115611d1757600080fd5b611d2384828501611bc4565b949350505050565b803560ff81168114610d2d57600080fd5b600080600080600080600060e0888a031215611d5757600080fd5b8735611d62816118bb565b96506020880135611d72816118bb565b95506040880135945060608801359350611d8e60808901611d2b565b925060a0880135915060c0880135905092959891949750929550565b600080600080600060808688031215611dc257600080fd5b8535611dcd816118bb565b94506020860135611ddd816118bb565b935060408601359250606086013567ffffffffffffffff811115611e0057600080fd5b611e0c888289016118fc565b969995985093965092949392505050565b60008060408385031215611e3057600080fd5b8235611e3b816118bb565b9150611e4960208401611d2b565b90509250929050565b600181811c90821680611e6657607f821691505b60208210811415611e8757634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600990820152683737ba1037bbb732b960b91b604082015260600190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000611d23602083018486611eb0565b634e487b7160e01b600052601160045260246000fd5b600082821015611f1557611f15611eed565b500390565b60018060a01b0385168152836020820152606060408201526000611f42606083018486611eb0565b9695505050505050565b600060208284031215611f5e57600080fd5b81518015158114610e6857600080fd5b634e487b7160e01b600052603260045260246000fd5b6000600019821415611f9857611f98611eed565b5060010190565b60008219821115611fb257611fb2611eed565b500190565b83815260406020820152600061091c604083018486611eb0565b6020808252600c908201526b6e6f74207265636f7665727960a01b604082015260600190565b60408152600061200a604083018561185b565b828103602084015261091c818561185b565b600060ff821660ff84168060ff0382111561203957612039611eed565b01939250505056fea2646970667358221220af38428c7eb44f06c049ef2230f226f33b89d817622fc80fa19aabd7ed9c780d64736f6c634300080c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000019316000000000000000000000000042ad6513979694794947475f82eb5e3d74d0c4cd000000000000000000000000f00b91839ff7a6ac6dddac7e73d2f222c19a9ec3000000000000000000000000000000000000000000000000000000000000000353504f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002453706f727473706172616469736520537769747a65726c616e642041472053686172657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003168747470733a2f2f7777772e73706f72747370617261646973652e63682f706167652f63726f7764696e76657374696e67000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _symbol (string): SPO
Arg [1] : _name (string): Sportsparadise Switzerland AG Shares
Arg [2] : _terms (string): https://www.sportsparadise.ch/page/crowdinvesting
Arg [3] : _totalShares (uint256): 1651040
Arg [4] : _owner (address): 0x42AD6513979694794947475f82eB5E3D74d0C4cD
Arg [5] : _recoveryHub (address): 0xf00B91839fF7A6AC6DddAC7e73D2F222C19A9Ec3

-----Encoded View---------------
14 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [3] : 0000000000000000000000000000000000000000000000000000000000193160
Arg [4] : 00000000000000000000000042ad6513979694794947475f82eb5e3d74d0c4cd
Arg [5] : 000000000000000000000000f00b91839ff7a6ac6dddac7e73d2f222c19a9ec3
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [7] : 53504f0000000000000000000000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000024
Arg [9] : 53706f727473706172616469736520537769747a65726c616e64204147205368
Arg [10] : 6172657300000000000000000000000000000000000000000000000000000000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000031
Arg [12] : 68747470733a2f2f7777772e73706f72747370617261646973652e63682f7061
Arg [13] : 67652f63726f7764696e76657374696e67000000000000000000000000000000


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.